【发布时间】:2010-11-03 13:07:02
【问题描述】:
我有一个简单的索引视图。当我查询它时,它很慢。首先,我向您展示模式和索引。然后是简单的查询。最后是查询计划屏幕。
更新:本文底部的解决方案证明。
架构
这就是它的样子:-
CREATE view [dbo].[PostsCleanSubjectView] with SCHEMABINDING AS
SELECT PostId, PostTypeId,
[dbo].[ToUriCleanText]([Subject]) AS CleanedSubject
FROM [dbo].[Posts]
我的 udf ToUriCleanText 只是用空字符替换各种字符。例如。用 '' 替换所有 '#' 字符。
然后我添加了两个索引:-
索引
主键索引(即聚集索引)
CREATE UNIQUE CLUSTERED INDEX [PK_PostCleanSubjectView] ON
[dbo].[PostsCleanSubjectView]
(
[PostId] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
还有一个非聚集索引
CREATE NONCLUSTERED INDEX [IX_PostCleanSubjectView_PostTypeId_Subject] ON
[dbo].[PostsCleanSubjectView]
(
[CleanedSubject] ASC,
[PostTypeId] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
现在,它有大约 25K 行。没什么大不了的。
当我执行以下查询时,它们都需要大约 4 秒。怎么回事?这应该是..基本上是即时的!
查询 1
SELECT a.PostId
FROM PostsCleanSubjectView a
WHERE a.CleanedSubject = 'Just-out-of-town'
查询 2(添加了另一个 where 子句项)
SELECT a.PostId
FROM PostsCleanSubjectView a
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1
我做错了什么? UDF 搞砸了?我认为,因为我已经索引了这个观点,所以它会成为现实。因此,它不必计算该字符串列。
这是查询计划的屏幕截图,如果有帮助的话:-
另外,请注意它使用的索引?为什么要使用那个索引?
那个索引是……
CREATE NONCLUSTERED INDEX [IX_Posts_PostTypeId_Subject] ON [dbo].[Posts]
(
[PostTypeId] ASC,
[Subject] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
是的,有什么想法吗?
更新 1:为 udf 添加了架构。
CREATE FUNCTION [dbo].[ToUriCleanText]
(
@Subject NVARCHAR(300)
)
RETURNS NVARCHAR(350) WITH SCHEMABINDING
AS
BEGIN
<snip>
// Nothing insteresting in here.
//Just lots of SET @foo = REPLACE(@foo, '$', ''), etc.
END
更新 2:解决方案
是的,这是因为我没有在视图上使用索引,并且必须手动确保我没有展开视图。服务器为Sql Server 2008 标准版。完整答案如下。
这是证据,WITH (NOEXPAND)
谢谢大家帮我解决这个问题:)
【问题讨论】:
-
ToUriCleanText 的确切返回类型是什么。是 varchar(max) 还是 nvarchar(max) ?
-
使用 UDF 架构更新原始帖子。返回 NVARCHAR(350)。
-
为什么不直接使用 REPLACE(REPLACE(REPLACE ....)))?它可能会更快,当然不会更慢。
-
真的那么快吗?目前我有.. er.. 15 左右 SET 行。
标签: sql sql-server tsql sql-server-2008 indexed-view