• 计划缓存


    今天我想进一步谈下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/

  • 相关阅读:
    一个简单的knockout.js 和easyui的绑定
    knockoutjs + easyui.treegrid 可编辑的自定义绑定插件
    Knockout自定义绑定my97datepicker
    去除小数后多余的0
    Windows Azure Web Site (15) 取消Azure Web Site默认的IIS ARR
    Azure ARM (1) UI初探
    Azure Redis Cache (3) 创建和使用P级别的Redis Cache
    Windows Azure HandBook (7) 基于Azure Web App的企业官网改造
    Windows Azure Storage (23) 计算Azure VHD实际使用容量
    Windows Azure Virtual Network (11) 创建VNet-to-VNet的连接
  • 原文地址:https://www.cnblogs.com/woodytu/p/6654771.html
Copyright © 2020-2023  润新知