gpt4 book ai didi

sql-server - 摆脱全索引扫描

转载 作者:行者123 更新时间:2023-12-02 08:42:04 25 4
gpt4 key购买 nike

以下查询执行得很差,因为对 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 条记录,优化器应该知道这一点(请参见下面的直方图)。

事实上,如果我获取 View 数据并将其放入堆表中(与索引 View 的结构相同),则查询是通过在较大的表上进行索引查找和内部联接循环而不是哈希来执行的加入(总成本从 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
)

分析文件 View 是启用统计且最新的索引 View 。

它有四列:

   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]))

最佳答案

您正在将 varchar 列 p4f.FileRelease 与 nvarchar 列 (af.path) 连接起来。由于数据类型不匹配,SQL 必须将一个类型转换为另一个类型(当然它不能从 nvarchar 转换为 varchar)。在将 af.path 转换为 nvarchar 时,它失去了使用索引查找/过滤这些值的能力,导致需要扫描和转换所有可能的行。

最好的解决方案是将数据存储为匹配的数据类型(将列 p4f.FileRelase 更改为 nvarchar,或将 af.path 更改为 varchar)。由于没有人可以修改现有的数据库结构,因此一种解决方法可能是在查询中将 af.path 显式转换为 varchar。测试一下并看看...当然,如果数据确实需要双字节格式,您就不能这样做。

关于sql-server - 摆脱全索引扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3188944/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com