SQL Server优化器特性-隐式谓词

原文:SQL Server优化器特性-隐式谓词

我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性-隐式谓词,并简单介绍在此特性下如何根据场景控制优化器的行为.

在这里我通过一个简单的实例来给大家说明下.

code

CREATE TABLE T1 (A INT, B INT)
CREATE TABLE T2 (A INT, B INT)

set showplan_text on

SELECT *
FROM T1 INNER JOIN T2 ON T1.A = T2.A

可以看出我的语句执行计划中优化器为我添加了T2.A=0这个谓词.如图1-1

图1-1

优化器根据语义逻辑判断,在不改变结果集的前提下认为提前在T2表中过滤出T2.A=0的结果集再参与下面运算可以提升效率,这样在未征得我们同意的情况下他就这样做了:)

这就是隐式谓词

既然这是SQL Server优化器的默认行为,那在我们自己要控制优化器行为的时候就少不了与其默认行为冲突.这里还是通过简单的实例说明.

code

select @@VERSION

SELECT *
FROM T1 inner hash JOIN T2 ON T1.A = T2.A
WHERE T1.A = 0

可以看到,我为sql加了个hash join的hint结果就出现了错误.如图1-2

图1-2

原因:默认的情况下优化器为我们加上了T2.A=0,t1,t2采用了相同的过滤条件,这时T1.A=T2.A自身的意义就不存在了,而hash join自身又需要等值链接(equijoin),此时报错就出现了.

延伸:其实在此种情况下select中检索凑到一起就可以了,抛错误让开发人员郁闷.微软注意到了这点,SQL2012中上述查询就没有问题了.如图1-3

图1-3

问题来了(不是挖掘机哪家强),如果我用了hint这种情况又该怎么办呢?就我们刚才的语句分析,hash join需要等值链接,可以根据表的定义规避他的隐式谓词特性造成的这个问题.

Where 条件中换成不等值不就可以了:)

Code

SELECT *
FROM T1 inner hash JOIN T2 ON T1.A = T2.A
WHERE T1.A >-1 and t1.A<=0

关于性能

可以看出在参与JOIN操作之前,优化器为我们过滤掉一部分数据,使得Join的消耗减轻,这是件好事儿,但凡事都有两个方面,为过滤掉的这部分数据他不是免费的,有时候可能会加重负担.

这里介绍一个trace flag 2324,他可以使优化器不采取隐式谓词行为,在特殊的场景下可以让我们的执行计划发挥的更好.

这里我通过一个简单的实例说明下.

code

select * from aaa inner join bbb
on aaa.ProductID=bbb.ProductID
where aaa.ProductID>1000 and aaa.ProductID<1500
go
select * from aaa inner join bbb
on aaa.ProductID=bbb.ProductID
where aaa.ProductID>1000 and aaa.ProductID<1500
option(querytraceon 2324)----禁用隐性谓词

可以看到由于由于隐式谓词在特殊的场景中(如数据分布比较倾斜.实例中ProductID=1001站了bbb表中的80%数据)过滤后的join反而不如整体数据参加join来得更快.如图1-4

图1-4

此处实例只为简单说明作用,实际生产中可能因为统计信息问题使得优化器采用了不合理的运算符(如对bbb中采用seek,则消耗巨大,而统计信息自身又不易更新)使得执行计划不合理影响整体性能.感兴趣的朋友可以自行测试.

注:TF2324只对不等值谓词起作用.等值谓词如果想规避隐性谓词,参考挖掘机的例子:)

结语:凡事都具有两面性,隐式谓词在绝大多数场景中是个很好的策略,微软也在一步步完善.但在优化器无法合理处理时,就需要我们人为介入.

时间: 2024-10-25 01:54:35

SQL Server优化器特性-隐式谓词的相关文章

SQL Server 优化器特性导致的内存授予相关BUG

原文:SQL Server 优化器特性导致的内存授予相关BUG 我们有时会遇到一些坑,要不填平,要不绕过.这里为大家介绍一个相关SQL Server优化器方面的特性导致内存授予的相关BUG,及相关解决方式,也顺便回答下邹建同学的相关疑问. 问题描述 一个简单的查询消耗了匪夷所思的内存.(邹建同学发现的) 原文链接 Code create table test_mem ( id int identity(1,1) primary key, itemid int not null, date dat

SQL Server优化器特性-动态检索

前段时间我写的文章SQL Server 隐式转换引发的躺枪死锁 中有的朋友评论回复说在SQL2008R2测试时并未出现死锁,自己一测果然如此,因此给大家带来的疑惑表示抱歉,这里我就解释下其原因. 回顾:SQL2012中发生死锁的原因已经向大家解释了,因为隐式转换造成的表扫描扩大了锁规模.但在SQL2008R2中就未有同样的现象出现,很显然锁规模没有扩大,原因在于SQL Server的优化器为我们做了额外的事情-动态检索 动态检索:基于索引查找的优势,SQL Server(部分版本)会尝试将一些情

高老大 ‘SQL Server 优化器特性导致的内存授予相关BUG’ 学习笔记

今天高老大出了好文章.在这里 自己本来对这一块比较混乱,正好借这个机会学习一下. 就用高老大的脚本.需要的直接去他那里找吧,这里就省了. 加查询优化标记前后对比 可以看到GrantedMemory是504928KB,大约是213096/1024=208.101562MB(这里的那个值好像每次都有差别,但是差距不太大.不影响效果) 加上跟踪标记后 4560/1024大概只有4MB吧. 差别很大吧~ 其实这里这些值还可能通过查询计划的XML里看,里面有更详细的信息. 如 <QueryPlan Deg

【转】SQL SERVER标量表达式的隐式转换

在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以在表达示的结果隐式转换成Int型. 同样对于标量函数,如一个表的一列是Int型,表中有两行值为2和3如果对这一列使用AVG函数,则结果是2,而不是2.5.但是如果这一列是Decimal类型的话,那么结果就是2.5.因为结果类型依据操作数据类型. 如下的一个Case语名 CASE WHEN <logi

SQL Server中提前找到隐式转换提升性能的办法

    http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前发现了这类潜在的风险岂不是更好?     那么我们来看一个简单的例子,如代码清单1所示.   1: SELECT * 2: FROM HumanResources.Employee 3: WHERE NationalIDNumber = 243322160 4:  5: SELECT * 6: FR

SQL Server 优化器+SQL 基础

http://www.cnblogs.com/shanksgao/tag/%E4%BC%98%E5%8C%96%E5%99%A8/ http://www.cnblogs.com/double-K/category/759248.html http://www.cnblogs.com/zhijianliutang/category/636063.html http://www.cnblogs.com/lonelyxmas/p/4685085.html       stack生成          

SQL Server有意思的数据类型隐式转换问题

写这篇文章的时候,还真不知道如何取名,也不知道这个该如何将其归类.这个是同事遇到的一个案例,案例比较复杂,这里抽丝剥茧,仅仅构造一个简单的案例来展现一下这个问题.我们先构造测试数据,如下所示: CREATE TABLE TEST (   ID    INT,   GOOD_TYPE  VARCHAR(12),   GOOD_WEIGHT NUMERIC(18,2) )   INSERT INTO dbo.TEST VALUES( 1, 'T1',1.27) SELECT  GOOD_TYPE,

SQL Server -&gt;&gt; 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表)

原文:SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表) 作为SQL Server 2016(CTP3.x)的另一个新特性,Temporal Table(历史表)记录了表历史上任何时间点所有的数据改动.Temporal Table其实早在ANSI SQL 2011就提出了,而SAP HANA, DB2和Oracle早已在它们的产品中加入/实现了这一特性.所以说微软其实是落后了几个竞争对手.既然在CTP3.0中加入了,相信

22. SQL -- SQL Server 2005 和SQL Server 2008新特性

SQL SERVER 2005 与SQL SERVER 2008 新特性   SQLSERVER 2005 新特性 Enhanced Data Types:存储最大8K-2G Partitioned Table(分区表):数据拆分管理 背景:一个公司,有目前现存数据以及历史数据,各在一台SER 上,服务器访问方式: SQL 2000 TABLE 1:在一张table 中,对数据进行分区 Enhanced Indexing Features SER 1 SER 2 现存数据 TABLE 1 TAB