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 ...
随机推荐
- Linux编程 20 shell编程(shell脚本创建,echo显示信息)
一概述 前面19章里已经掌握了linux系统和命令行的基础知识,从本章开始继续学习shell脚本的基础知识.在大量编辑shell脚本前,先来学习下一些基本概念. 1.1 使用多个命令 Shell ...
- mysql 开发基础系列5 运算符
1. 算术运算符 2.比较运算符 注意NULL值不能用= 运算符 SELECT * FROM t WHERE c =NULL; -- 需要改成 SELECT * FROM t WHERE c IS N ...
- sql server 索引阐述系列一索引概述
一. 索引概述 关于介绍索引,有一种“文章太守,挥毫万字,一饮千钟”的豪迈感觉,因为索引需要讲的知识点太多.在每个关系型数据库里都会作为重点介绍,因为索引关系着数据库的整体性能, 它在数据库性能优化里 ...
- 经典中的品味:第一章 C++的Hello,World!
摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! "程序设计要通过编写程序的实践来学习"-Brian ...
- 菜鸟系列docker——docker仓库(2)
1.仓库Registry 我们一般的镜像都是保存在仓库中,这样在其他服务器上可以直接从仓库获取镜像.仓库一般分为公共registry和私有registry.公共registry一般是Docker公司负 ...
- More Effective C# 【前戏】
买了很多很多书,想到就买,觉得有需要就买.买书的情况是不一样的:有时候,买的时候还是比较空,买来之后工作开始忙起来了,就没怎么看:有时候,买的时候比较忙,忙的乱了方寸,觉得有必要找本书来静心一下.不过 ...
- centos7安装遇到的坑
1.安装中遇到what is the location of the gcc program on your machine 直接输入 no.意思就是跳过gcc的安装了.但是系统虽然安装了vmware ...
- TensorFlow中的并行执行引擎——StreamExecutor框架
背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 在前一篇文章中,我们梳理了TensorFlow中各种异构Device的添加和注 ...
- python学习笔记(三)、字典
字典是一种映射类型的数据类型.辣么什么是映射呢?如果看过<数据结构与算法>这一本书的小伙伴应该有印象(我也只是大学学习过,嘻嘻). 映射:就是将两个集合一 一对应起来,通过集合a的值,集合 ...
- 【Java每日一题】20170207
20170206问题解析请点击今日问题下方的“[Java每日一题]20170207”查看(问题解析在公众号首发,公众号ID:weknow619) package Feb2017; public cla ...