Hen*_*sen 9 sql-server optimization execution-plan nonclustered-index sql-server-2017
我在 SQL Server 2017 执行计划中看到过这个警告:
警告:操作导致剩余 IO [原文如此]。实际读取的行数为 (3,321,318),但返回的行数为 40。
这是 SQLSentry PlanExplorer 的一个片段:
为了改进代码,我添加了一个非聚集索引,以便 SQL Server 可以访问相关行。它工作正常,但通常会有太多(大)列包含在索引中。它看起来像这样:
如果我只添加索引而不包含列,如果我强制使用索引,它看起来像这样:
显然,SQL Server 认为键查找比剩余 I/O 昂贵得多。我有一个没有太多测试数据的测试设置(还),但是当代码投入生产时,它需要处理更多的数据,所以我很确定需要某种非聚集索引。
当您在 SSD 上运行时,键查找真的那么昂贵,我必须创建全脂索引(有很多包含列)?
执行计划: https : //www.brentozar.com/pastetheplan/?id=SJtiRte2X它是长存储过程的一部分。寻找IX_BatchNo_DeviceNo_CreatedUTC
.
Pau*_*ite 17
优化器使用的成本模型正是:一个模型。它在广泛的工作负载、广泛的数据库设计和广泛的硬件上产生通常良好的结果。
您通常不应假设单个成本估算与特定硬件配置上的运行时性能密切相关。成本计算的重点是允许优化器在相同逻辑操作的候选物理替代方案之间做出有根据的选择。
当您真正深入了解细节时,熟练的数据库专业人员(有时间花在调整重要查询上的时间)通常可以做得更好。就此而言,您可以将优化器的计划选择视为一个很好的起点。在大多数情况下,该起点也将是终点,因为找到的解决方案已经足够好了。
根据我的经验(和意见),SQL Server 查询优化器的查找成本比我希望的要高。这在很大程度上是随机物理 I/O 与顺序访问相比比今天通常情况要昂贵得多的日子的宿醉。
尽管如此,即使在 SSD 上,或者最终甚至在完全从内存中读取时,查找也可能很昂贵。遍历 b 树结构不是免费的。显然,随着你做更多的事情,成本会增加。
包含的列非常适合读取密集型 OLTP 工作负载,在这种情况下,索引空间使用和更新成本与运行时读取性能之间的权衡是有意义的。还需要考虑计划稳定性的权衡。完全覆盖索引避免了优化器的成本模型何时可能从一种替代方案过渡到另一种方案的问题。
只有您可以决定权衡在您的情况下是否值得。在有代表性的数据样本上测试这两种选择,并做出明智的选择。
在您添加的问题评论中:
你是说SQL Server不知道剩余IO的成本吗?
不,优化器确实考虑了剩余 I/O 的成本。事实上,就优化器而言,非 SARGable 谓词在单独的过滤器中进行评估。在优化后重写期间,此过滤器作为残差被推入搜索或扫描。