zoukankan      html  css  js  c++  java
  • 计划缓存

    今天我想进一步谈下SQL Server里的计划缓存和它的副作用。我们都知道,每个提交到SQL Server的逻辑查询,会编译为物理执行计划。这个执行计划然后会缓存为所谓的计划缓存,用于后期重用。现在我们首先来谈下即席SQL语句和它的负作用,还有它们带来的性能问题。

    即席SQL语句(Adhoc SQL Statements)

    每次当你提交一个即席SQL语句到SQL Server,对于每个特定查询,都会生成一个执行计划。“特定查询”是什么意思?答案很简单:SQL Server对每个完整的SQL语句(包括你的参数值)生成一个哈希值,并使用这个哈希值作为计划缓存的查找值。如果使用这个哈希值找到一个执行计划,计划就会重用,否则在计划缓存里会编译一个新的执行计划。假设你提交下列3个查询到SQL Server:

    SELECT * FROM Sales.SalesOrderHeader
    WHERE CustomerID = 11000
    GO
    
    SELECT * FROM Sales.SalesOrderHeader
    WHERE CustomerID = 30052
    GO
    
    SELECT * FROM Sales.SalesOrderHeader
    WHERE CustomerID = 11223
    GO

    对于这3个查询,SQL Server编译3个不同的执行计划,因为你提供了硬编码的参数值。因此3个查询间会计算不同的的哈希值,不会找到已缓存的计划。作为副作用,在计划缓存里,现在你有近3个近乎一样的查询有3个不同的计划。这个特定问题被称为计划缓存污染

    你刚用不同的执行计划污染了你的计划缓存,这很难重用(因为硬编码的参数值),而且你在浪费可以被SQL Server里其它组件使用的有用内存。缓存的目的应该提高重用数,但使用即席SQL语句就做不到。

    计划稳定性

    假设你为你的SQL语句使用参数值,或者你甚至使用存储过程。在这个情况下,SQL Server非常容易重用缓存的执行计划。但即使重用缓存的执行计划,你回引入性能问题。例如SQL Server为一个查询编译了一个执行计划,它回进行书签查找,因为非聚集索引没有覆盖你的查询:

    我们提过,书签查找只有在从表里获取一些数据才有意义。如果你越过了临界点,使用全表扫描或聚集索引扫描更高效。但如果SQL Server冲了缓存的执行计划,这个选项就不会考虑太多——SQL Server会盲目重用你的计划——这时你的性能就会很差!可以看下面的例子:

    这里SQL盲目重用了有书签查找的缓存计划。你会看到估计和实际行数有很大差别!SQL Server在假设从查询里只返回一条记录来编译和缓存计划。但实际上从SQL Server我们拿回1499条记录。你看到的执行计划,是假设只有一条记录返回的情况下优化——考虑下这个情况。

    这里潜在的根源是你的计划不稳定。基于估计行数,你得到有书签查找的缓存计划,如果你越过临界点,会是表/聚集索引扫描。这是我们经常碰到的常见SQL Server性能问题。

    你如何解决这个问题?简单:通过覆盖非聚集索引来避免书签查找。使用这个方法你会获得计划稳定性,不管你的输入参数,你会得到同样的性能。

    小结

    今天你学到了SQL Server里,计划缓存的双刃剑:在一方面,计划缓存非常强大,因为你可以重用计划缓存避免编译资源占用。在另一方面,他非常危险,使用定型的执行计划,你的计划不再稳定,这就意味着你不能再保证性能。

    感谢关注!

    原文链接

    https://www.sqlpassion.at/archive/2017/03/20/plan-caching/

  • 相关阅读:
    【uniapp】改善中大型uniapp小程序项目开发体验
    vite试玩:老项目启动从6分钟到秒开
    修剪AST树减少webapck打包尺寸
    librispeech数据集下载
    语音识别性能评估方法
    2021.12.11 物联网考试
    2021.12.15 课程总结+加分项
    2021.12.9 观影大数据分析
    2021.12.8 Docker服务
    2021.12.10 阿里云服务器创建
  • 原文地址:https://www.cnblogs.com/woodytu/p/6654771.html
Copyright © 2011-2022 走看看