Eri*_*ing 14 performance index sql-server
我有一个 SQL Server 数据库,其中的查询速度很慢,而且有很多锁定和阻塞。
当我查看缺失的索引 DMV 和查询计划时,没有任何建议。
这是为什么?
Eri*_*ing 17
我们将更详细地研究其中的一些原因,并讨论该功能的一些一般限制。
首先,来自:缺失索引功能的限制:
- 它没有指定在索引中使用的列的顺序。
如本问答中所述:SQL Server 如何确定缺失索引请求中的键列顺序?,索引定义中列的顺序由 Equality vs Inequality 谓词决定,然后是表中的列序数位置。
没有对选择性的猜测,并且可能有更好的顺序可用。弄清楚这一点是你的工作。
特殊索引
缺少索引请求也不包括“特殊”索引,例如:
缺失索引键列是从用于过滤结果的列中生成的,例如:
Missing Index Included 列是从查询所需的列中生成的,例如:
尽管很多时候,您排序或分组的列作为关键列是有益的。这可以追溯到限制之一:
- 它不是为了微调索引配置。
例如,此查询不会注册丢失的索引请求,即使在 LastAccessDate 上添加索引会阻止需要排序(并溢出到磁盘)。
SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;
Run Code Online (Sandbox Code Playgroud)
也没有对位置进行分组查询。
SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location
Run Code Online (Sandbox Code Playgroud)
嗯,是的,但总比没有好。把缺少索引请求想象成一个哭泣的婴儿。你知道有问题,但作为一个成年人,你需要弄清楚这个问题是什么。
放轻松,巴哥。我们快到了。
如果启用TF 2330,则不会记录丢失的索引请求。要了解您是否启用了此功能,请运行以下命令:
DBCC TRACESTATUS;
Run Code Online (Sandbox Code Playgroud)
重建索引将清除丢失的索引请求。因此,在您开始 Hi-Ho-Silver-Away 重建每个索引之前,一旦有一小部分碎片潜入,请考虑您每次这样做时要清除的信息。
无论如何,您可能还想考虑为什么对索引进行碎片整理没有帮助。除非您使用Columnstore。
添加、删除或禁用索引将清除该表的所有缺失索引请求。如果您正在对同一个表进行多次索引更改,请确保在进行任何更改之前将它们全部编写好。
如果一个计划足够简单,索引访问选择足够明显,成本足够低,你就会得到一个平凡的计划。
这实际上意味着优化器无需做出基于成本的决策。
通过保罗怀特:
哪些类型的查询可以从 Trivial Plan 中受益的细节经常变化,但是诸如连接、子查询和不等式谓词之类的东西通常会阻止这种优化。
当计划不重要时,不会探索额外的优化阶段,也不会请求缺失的索引。
查看这些查询与其计划之间的区别:
SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2;
SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2
AND 1 = (SELECT 1);
Run Code Online (Sandbox Code Playgroud)
第一个计划是微不足道的,没有显示任何请求。可能存在错误阻止丢失索引出现在查询计划中的情况;不过,它们通常更可靠地记录在缺失的索引 DMV 中。
即使使用索引,优化器也无法有效使用索引的谓词可能会阻止它们被记录。
通常不可 SARGable 的事情是:
SELECT *
FROM dbo.Users AS u
WHERE ISNULL(u.Age, 1000) > 1000;
SELECT *
FROM dbo.Users AS u
WHERE DATEDIFF(DAY, u.CreationDate, u.LastAccessDate) > 5000
SELECT *
FROM dbo.Users AS u
WHERE u.UpVotes + u.DownVotes > 10000000
DECLARE @ThisWillHappenWithStoredProcedureParametersToo NVARCHAR(40) = N'Eggs McLaren'
SELECT *
FROM dbo.Users AS u
WHERE u.DisplayName LIKE @ThisWillHappenWithStoredProcedureParametersToo
OR @ThisWillHappenWithStoredProcedureParametersToo IS NULL;
Run Code Online (Sandbox Code Playgroud)
这些查询都不会注册丢失的索引请求。有关这些的更多信息,请查看以下链接:
拿这个指数:
CREATE INDEX ix_whatever ON dbo.Posts(CreationDate, Score) INCLUDE(OwnerUserId);
这个查询看起来没问题:
SELECT p.OwnerUserId, p.Score
FROM dbo.Posts AS p
WHERE p.CreationDate >= '20070101'
AND p.CreationDate < '20181231'
AND p.Score >= 25000
AND 1 = (SELECT 1)
ORDER BY p.Score DESC;
Run Code Online (Sandbox Code Playgroud)
该计划是一个简单的寻求...
但是因为前导键列用于选择较少的谓词,我们最终做了比我们应该做的更多的工作:
表“帖子”。扫描计数 13,逻辑读取 136890
如果我们改变索引键列顺序,我们做的工作就会少很多:
CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);
阅读量明显减少:
表“帖子”。扫描计数 1,逻辑读取 5
在某些情况下,SQL Server 将选择通过索引假脱机动态创建索引。当存在索引假脱机时,不会出现丢失的索引请求。当然,自己添加索引可能是个好主意,但不要指望 SQL Server 帮助您解决这个问题。
| 归档时间: |
|
| 查看次数: |
1391 次 |
| 最近记录: |