以下查询的执行效果不佳,因为P4FileReleases中的650万条记录完全非聚簇索引扫描,后面是散列连接。我正在寻找优化程序对搜索进行扫描的可能原因。摆脱完整索引扫描
SELECT p4f.FileReleaseID
FROM P4FileReleases p4f
INNER JOIN AnalyzedFileView af
ON p4f.FileRelease = (af.path+'#'+cast(af.revision as varchar))
WHERE (af.tracked_change_id = 1)
从我所知道的,我看不出有任何理由优化挑P4FileReleases的扫描。 WHERE子句将正确数据集的大小限制为大约1K条记录,优化器应该知道它(参见下面的直方图)。
如果事实上,如果我将视图数据放入一个堆表(与索引视图的结构相同),那么查询将在较大的表上执行索引查找,而不是一个内部联接循环哈希连接(总成本从145下降到1左右)。
关于什么可能会抛出优化器的想法?
详情。 Sql Server 2008(v。10.0.2757.0)。
P4FileReleases表 存放650万条记录
CREATE TABLE [dbo].[P4FileReleases](
[FileReleaseID] [int] IDENTITY(1,1) NOT NULL,
[FileRelease] [varchar](254) NOT NULL,
-- 5 more fields
CONSTRAINT [CIX_P4FileReleases_FileReleaseID_PK] PRIMARY KEY CLUSTERED
(
[FileReleaseID] ASC
),
CONSTRAINT [NCIX_P4FileReleases_FileRelease] UNIQUE NONCLUSTERED
(
[FileRelease] ASC
)
AnalyzedFileView 是启用并且最新的统计数据的索引视图。
它有四列:
key int (int, PK) - clustered index
tracked_change_id (int, FK) - non-unique, non-clustered index (covering 'path', 'revision')
path (nvarchar(1024), null)
revision (smallint, null)
tracked_change_id直方图:
1 0 1222 0 1
4 0 787 0 1
8 0 2754 0 1
12 0 254 0 1
13 0 34 0 1
查询计划
|--Parallelism(Gather Streams)
|--Hash Match(Inner Join, HASH:([Expr1011])=([Expr1010]), RESIDUAL:([Expr1010]=[Expr1011]))
|--Bitmap(HASH:([Expr1011]), DEFINE:([Bitmap1015]))
| |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([Expr1011]))
| |--Compute Scalar(DEFINE:([Expr1011]=([qpsitools].[dbo].[analyzed_file_view].[path]+N'#')+CONVERT_IMPLICIT(nvarchar(30),CONVERT(varchar(30),[qpsitools].[dbo].[analyzed_file_view].[revision],0),0)))
| |--Index Seek(OBJECT:([qpsitools].[dbo].[analyzed_file_view].[tracked_change_id]), SEEK:([qpsitools].[dbo].[analyzed_file_view].[tracked_change_id]=(1)) ORDERED FORWARD)
|--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([Expr1010]), WHERE:(PROBE([Bitmap1015],[Expr1010])))
|--Compute Scalar(DEFINE:([Expr1010]=CONVERT_IMPLICIT(nvarchar(254),[Blueprint].[dbo].[P4FileReleases].[FileRelease] as [p4f].[FileRelease],0)))
|--Index Scan(OBJECT:([Blueprint].[dbo].[P4FileReleases].[NCIX_P4FileReleases_FileRelease] AS [p4f]))
即使将它作为匹配类型存储,他将两个字段与#inbetween拼接在一起的事实也会强制扫描不会吗? – 2010-07-06 18:42:27
太棒了!看起来像varchar vs nvarchar是问题。谢谢! – 2010-07-06 19:14:18
@Mike M,“... WHERE ColName = @Variable”和“... WHERE ColName = @Variable + @Variable”之间的SQL *与*之间几乎没有什么区别。它需要你产生的任何价值,并在表格中查找它。 – 2010-07-06 20:34:56