SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 测试总结
关于SQL Server的查询提示OPTION (OPTIMIZE FOR UNKNOWN) ,它是解决参数嗅探的方法之一。 而且对应的SQL语句会缓存,不用每次都重编译。关键在于它的执行计划的准确度问题, 最近在优化的时候,和同事对于这个查询提示(Query Hint)有一点分歧,遂动手实验验证、总结了一些东西。
关于提示OPTION (OPTIMIZE FOR UNKNOWN),它会利用统计数据和标准算法生成一个折中、稳定的执行计划,但是它是无法利用直方图(histogram)信息来生成执行计划。官方文档的介绍如下:
OPTIMIZE FOR 编译和优化查询时提示查询优化器对本地变量使用特定值。仅在查询优化期间使用该值,在查询执行期间不使用该值。
UNKNOWN
指定查询优化器在查询优化期间使用统计数据而不是初始值来确定局部变量的值。OPTIMIZE FOR 可以抵消优化器的默认参数检测行为,也可在创建计划指南时使用
OPTIMIZE FOR UNKNOWN
指示查询优化器在查询已经过编译和优化时为所有局部变量使用统计数据而不是初始值,包括使用强制参数化创建的参数。有关强制参数化的详细信息,请参阅强制参数化。
如果在同一查询提示中使用 OPTIMIZE FOR @variable\_name = literal_constant 和 OPTIMIZE FOR UNKNOWN,则查询优化器将对特定的值使用指定的 literal_constant,而对其余变量使用 UNKNOWN。这些值仅用于查询优化期间,而不会用于查询执行期间。
OPTIMIZE FOR UNKNOWN是否会用直方图数据呢? 不会,OPTIMIZE FOR UNKNOWN只会用简单的统计数据。我们以how-optimize-for-unknown-works这篇博客中的例子来演示一下, 下面测试环境为SQL Server 2014,数据库为AdventureWorks2014
CREATE PROCEDURE test (@pid int)
AS
SELECT * FROM [Sales].[SalesOrderDetail]
WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);
为了消除统计信息不准确会干扰测试结果,我们手工更新一下统计信息。
UPDATE STATISTICS [Sales].[SalesOrderDetail] WITH FULLSCAN;
我们在SSMS里面点击“包含实际执行计划”选项,然后测试执行该存储过程,如下截图所示: 执行计划居然走聚集索引扫描
EXEC test @pid=709

Filter里面过滤的记录为456.079,而实际上ProductID=709的记录有188条,那么优化器是怎么估计判断记录数为456.709的呢?


其实优化器是这样来估计的:它使用ProductID列的密度(Density)* Rows来计算的
SELECT 0.003759399 *121317 ~= 456.079008483 ~= 456.079
而ProductID列的密度(Density)的计算是这样来的:
ProductID的值有266个,可以用下面SQL获取ProductID的值个数
SELECT COUNT(DISTINCT ProductID) FROM Sales.SalesOrderDetail
SELECT 1.0/266 ~= 0.003759
然后你可以使用任意不同的参数测试,例如707、712......, 你会发现使用查询提示OPTION (OPTIMIZE FOR UNKNOWN)后,优化器会总是使用相同的执行计划。也就是说这个查询提示生成的执行计划是一个“折中的执行计划” ,对于数据分布倾斜的比较厉害(数据分布极度不均衡)的情况下,是极度不建议使用查询提示OPTION (OPTIMIZE FOR UNKNOWN)的。
本人曾经一度对使用OPTION(RECOMPILE)还是OPTION (OPTIMIZE FOR UNKNOWN)感到困惑和极度难以取舍,后面总结了一下:
1:执行不频繁的存储过程,使用OPTION(RECOMPILE)要优先与OPTION (OPTIMIZE FOR UNKNOWN)
2:执行频繁的存储过程,使用OPTION (OPTIMIZE FOR UNKNOWN)要优先于OPTION(RECOMPILE)
3:数据分布倾斜的厉害的情况下,优先使用OPTION(RECOMPILE)
4: 使用OPTION (OPTIMIZE FOR UNKNOWN)会生成一个稳定、统一的执行计划,如果这个执行计划的效率基本能满足用户需求,那么优先使用OPTION (OPTIMIZE FOR UNKNOWN)
参考资料:
https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2008/ms181714(v=sql.100)
http://www.benjaminnevarez.com/2010/06/how-optimize-for-unknown-works/
https://blogs.msdn.microsoft.com/sqlprogrammability/2008/11/26/optimize-for-unknown-a-little-known-sql-server-2008-feature/
SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 测试总结的更多相关文章
- Top 10 steps to optimize data access in SQL Server
2009年04月28日 Top 10 steps to optimize data access in SQL Server: Part I (use indexing) 2009年06月01日 To ...
- .Net EF Core数据库使用SQL server 2008 R2分页报错How to avoid the “Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement.”
一. 问题说明 最近.Net EF core 程序部署到服务器,服务器数据库安装的是SQL server 2008 R2,我本地用的的是SQL server 2014,在用到分页查询时报错如下: H ...
- .NET Core EF框架使用SQL server 2008数据库分页问题:Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement
一. 问题 最近.Net Core程序部署到服务器,采用EF6.本地数据库是SQL server 2016,服务器数据库安装的是SQL server 2008 R2,在用到分页查询时报错如下: { & ...
- 谈一谈SQL Server中的执行计划缓存(下)
简介 在上篇文章中我们谈到了查询优化器和执行计划缓存的关系,以及其二者之间的冲突.本篇文章中,我们会主要阐述执行计划缓存常见的问题以及一些解决办法. 将执行缓存考虑在内时的流程 上篇文章中提到了查询优 ...
- SQL SERVER 中的提示
提示是指定的强制选项或策略,由 SQL Server 查询处理器针对 SELECT.INSERT.UPDATE 或 DELETE 语句执行. 提示将覆盖查询优化器可能为查询选择的任何执行计划. 注意: ...
- (转)SQL Server 性能调优(cpu)
摘自:http://www.cnblogs.com/Amaranthus/archive/2012/03/07/2383551.html 研究cpu压力工具 perfom SQL跟踪 性能视图 cpu ...
- SQL Server 2016的数据库范围内的配置
SQL Server 2016真的让人眼前一亮.几天前微软就提供了RCO(候选发布版)版本的下载.我已经围观了一圈RCO版本,其中一个最拽的功能是数据库范围内的配置(Database Scoped C ...
- 《Troubleshooting SQL Server》读书笔记-CPU使用率过高(下)
<Troubleshooting SQL Server>读书笔记-CPU使用率过高(下) 第三章 High CPU Utilization. CPU使用率过高的常见原因 查询优化器会尽量从 ...
- Microsoft SQL Server Trace Flags
Complete list of Microsoft SQL Server trace flags (585 trace flags) REMEMBER: Be extremely careful w ...
随机推荐
- 【Android基础】Fragment 详解之Fragment介绍
Fragment在Android 3.0( API 11)引入,是为了支持在大屏上显示更加动态.灵活的UI,比如在平板和电视上.Fragment可以看作是嵌套的Activity,类似ActivityG ...
- [工具向]__申请,下载,使用百度地图api
前言 api即应用程序接口,在我们的日常开发中,我们不仅可以在开源代码仓库(,github,码云)中获得很大的帮助,在日常开发中占重要地位的另一个东西就是api,我们可以使用众多的第三方编写的优秀的a ...
- Deep Learning中的Large Batch Training相关理论与实践
背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 在分布式训练时,提高计算通信占比是提高计算加速比的有效手段,当网络通信优化到一 ...
- SpringBoot学习(七)-->SpringBoot在web开发中的配置
SpringBoot在web开发中的配置 Web开发的自动配置类:在Maven Dependencies-->spring-boot-1.5.2.RELEASE.jar-->org.spr ...
- React Fiber源码分析 第三篇(异步状态)
先附上流程图~ 调用setState时, 会调用classComponentUpdater的enqueueSetState方法, 同时将新的state作为payload参数传进 enqueueSetS ...
- C#爬虫----Fiddler 插件开发 自动生成代码
哈喽^_^ 一般我们在编写网页爬虫的时候经常会使用到Fiddler这个工具来分析http包,而且通常并不是分析一个包就够了的,所以为了把更多的时间放在分析http包上,自动化生成封包代码就尤为重要了( ...
- Java高并发 -- 线程池
Java高并发 -- 线程池 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 在使用线程池后,创建线程变成了从线程池里获得空闲线程,关闭线程变成了将线程归坏给线程池. ...
- 元类实现ORM
1. ORM是什么 ORM 是 python编程语言后端web框架 Django的核心思想,"Object Relational Mapping",即对象-关系映射,简称ORM. ...
- 【Web前端】用CSS3实现弹幕
初版 用css3来实现弹幕确实比较简单,只需要设置动画让弹幕从屏幕右侧移动到屏幕左侧即可,一开始是这样实现的 .danmu { position: fixed; left: %; animation: ...
- elasticsearch概念
1.elasticsearch的核心概念 (1)Near Realtime(NRT):近实时,从写入数据到数据可以被搜索到有一个小延迟(大概1秒):基于es执行搜索和分析可以达到秒级 (2)Clust ...