Vat*_*lav 6 sql-server optimization statistics
我在存储过程中有一个查询,它必须列出一个范围内的所有日期,并从表中加入日期(如果当天存在的话)。
这个过程是在我成为DBA之前创建的,所以我想我可以优化一下。但是,我似乎碰到了一堵砖墙,我不明白为什么。
过程的当前实现从两个普通表(我们称它们为 TableA 和 TableB)中作为派生查询(在 FROM 子句中)中选择数据,然后将其作为 RIGHT JOIN 放在上面:
RIGHT JOIN (
SELECT DATEADD(DAY,number,@DateFrom) AS DATE
FROM (
SELECT DISTINCT number
FROM master.dbo.spt_values
WHERE name IS NULL
) n
WHERE DATEADD(DAY,number,@DateFrom) <= @DateTo
) AS y ON derived.Date = y.Date -- "derived" is an alias of the derived query
Run Code Online (Sandbox Code Playgroud)
由于在多个过程中使用了相同的代码,我想我会创建一个日期从 2005-01-01 到 2039-01-01 的表:
CREATE TABLE Dates(
[Date] DATE NOT NULL PRIMARY KEY
)
Run Code Online (Sandbox Code Playgroud)
该表是从具有日期维度的仓库中填充的。
所以,我写的不是那个 RIGHT JOIN,而是:
FROM Dates d
LEFT JOIN derived ON derived.Date = d.[Date] -- the "derived" table was moved to CTE, since that's easier to read
WHERE d.[Date] BETWEEN @DateFrom AND @DateTo
Run Code Online (Sandbox Code Playgroud)
对代码感到满意,我打开了 STATISTICS IO 并执行了两个版本的过程代码,结果完全震惊了。
旧查询的统计信息:
表'表A'。扫描计数0,逻辑读456516,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
表'表B'。扫描计数 367,逻辑读取 3949,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表'spt_values'。扫描计数 1,逻辑读取 14,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
新查询的统计信息:
表“工作台”。扫描计数 0,逻辑读 0,物理读 0,预读 0,lob 逻辑读 0,lob 物理读 0,lob 预读 0。
表'表B'。扫描计数1,逻辑读1767,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
表'表A'。扫描计数 1,逻辑读取 6,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表“日期”。扫描计数 1,逻辑读取 3,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
但是,第二个查询速度较慢。
在查看执行计划时,它说第一个查询只占用了成本的 2%,而第二个查询占用了 98%。两者在 TableB(较大的)上具有相同的索引查找,区别在于:
在这两种情况下,从索引查找返回的行数都是 228258。
并采用 XML 格式: 两个查询的 XML 计划
我的问题是:
小智 2
执行计划的百分比成本来自优化器的估计,即使生成了实际的执行计划。实际执行计划确实使用准确的计划,并包括估计行数和实际行数。行计数之间的差异有助于确定估计的准确性。
在子查询和将其与 中的列进行比较之间的某个位置derived
,优化器无法正确估计有多少行将匹配。它猜测会有 18 行,而derived
实际数量超过 220,000 行。另一个线索是警告Cardnality Estimate: CONVERT(nvarchar(35),[mssqlsystemresource].[sys].[spt_values].[name],0)
消息SELECT
警告消息。
如果您要使用其他内容检查查询运行长度,例如STATISTICS TIME
我希望它们更接近,并且第二个查询可能运行得更快。
这是另一个有类似情况的计划分析。(SQL Server Plan Explorer)(向Kendra Little致敬介绍如何愚弄优化器)
估计显示成本分配为 93%/7%,但通过查看实际的 CPU、时间或 IO,差异并没有那么极端。IO 约为 75%/25%,CPU 约为 60%/40%。(我试图想出一些更均匀的东西,但没能做到。)
归档时间: |
|
查看次数: |
1338 次 |
最近记录: |