SQL 2012 数据仓库类型环境...
我在类型 2 维度表上有一个非聚集索引,我将其称为 DimStudent。
索引定义如下,数据类型和上下文括号中的其他信息:
(
[StudentID] ASC (VARCHAR(10))
,[EffectiveStartDate] ASC (SMALLDATETIME)
,[EffectiveEndDate] ASC (SMALLDATETIME)
)
INCLUDE [StudentKey] (INT, IDENTITY, PK).
有问题的查询正在 SSIS ETL 包中运行,定义如下。它在使用部分缓存的查找转换中指定,在使用自定义查询部分的高级选项卡中指定,该部分主要由 Visual Studio 自动生成(将 [refTable] 别名和 SELECT * 放入查询中)并进行一些修改SCD2 查找用法的查询:
select * from (SELECT
LTRIM(RTRIM(StudentID)) AS StudentID_Trimmed
,StudentKey
,EffectiveStartDate
,EffectiveEndDate
FROM dbo.DimStudent
)
AS [refTable]
where [refTable].[StudentID_Trimmed] = @P1
and [refTable].[EffectiveStartDate] <= @P2
and [refTable].[EffectiveEndDate] > @P3
请注意,查询中列的顺序是学生 ID (@P1),然后是开始日期 (@P2),然后是结束日期 (@P3)。
另请注意,我目前正在修剪 StudentID。我已经确定这不再是必需的(出于某种原因在某些时候它是必需的),并且我已经在努力更改 ETL 以删除该 TRIM 方面。
在这个查询的查询计划中(使用 Adam Macahanic 的 sp_WhoIsActive),我已经确认它正在使用这个索引进行非集群扫描。当我查看扫描运算符的属性时,它将谓词列为:(删除了数据库和模式)
[DimStudent].[EffectiveStartDate] <= **[@P2]**
AND [DimStudent].[EffectiveEndDate] > **[@P3]**
AND ltrim(rtrim([DimStudent].[StudentID])) = **[@P1]**
我的问题是:
为什么查询计划中的谓词顺序(@P2、@P3、@P1)与查询的编写顺序不同?(@P1, @P2, @P3) TRIM 引起的?
为什么它是扫描而不是搜索,因为索引是为这个查询设计的?由TRIM(不是SARGable)引起的?
SQL Server 认为日期更具选择性,因为它知道开始日期和结束日期字段中的值是什么样的。由于对 StudentId 列进行了修整,因此它不知道有多少行。一旦您将其修复为不使用修剪后的计算列,它应该会按预期工作。
你在这里发生了几件事。首先,由于您使用的是修剪,因此优化器可能首先使用日期范围,因为它可以更好地了解要查找的位置以及将返回多少行。
第二。您进行扫描很可能是因为您请求了部分缓存,因此它在各个行上不匹配。如果你没有缓存查找,我想你会开始看到索引查找。
第三。如果您的维度表相对较大并且您的事实表也很大,那么简单地对学生表进行完整缓存可能是有意义的。