博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
执行计划--WHERE条件的先后顺序对执行计划的影响
阅读量:7113 次
发布时间:2019-06-28

本文共 3814 字,大约阅读时间需要 12 分钟。

在编写SQL时,会建议将选择性高(过滤数据多)的条件放到WHERE条件的前面,这是为了让查询优化器优先考虑这些条件,减少生成最优(或相对最优)的执行计划的时间,但最终的执行计划生成过滤顺序还是决定这些条件的选择性与判断bool值的容易程度

测试代码:

GOSELECT *INTO #T1FROM sys.all_columnsGOSELECT *INTO #T2FROM sys.all_columnsGOSELECT *INTO #T3FROM sys.all_columnsGOSET STATISTICS IO ONSET STATISTICS TIME ONGOSELECT * FROM #T1 AS T1WHERE T1.[object_id]=3AND (SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1SELECT * FROM #T1 AS T1WHERE (SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1AND T1.[object_id]=3

执行计划:

可以从查询计划看出,无论T1.[object_id]=3在何处,其计算bool值相对简单,而(SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1 需要访问其他表,因此执行优化器优先执行T1.[object_id]=3,在满足T1.[object_id]=3为ture时再坚持行是否满足(SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1。

 

但对于以下查询:

SELECT * FROM #T1 AS T1WHERE (SELECT COUNT(1) FROM #T3 AS T3 WHERE T3.[object_id]>T1.[object_id])<1AND (SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1SELECT * FROM #T1 AS T1WHERE  (SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1AND (SELECT COUNT(1) FROM #T3 AS T3 WHERE T3.[object_id]>T1.[object_id])<1

执行计划:

执行统计:

(25 row(s) affected)Table 'Worktable'. Scan count 29, logical reads 36813, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table '#T3_________________________________________________________________________________________________________________00000000000C'. Scan count 4, logical reads 80, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table '#T1_________________________________________________________________________________________________________________000000000009'. Scan count 5, logical reads 59, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table '#T2_________________________________________________________________________________________________________________00000000000A'. Scan count 1, logical reads 59, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.(1 row(s) affected) SQL Server Execution Times:   CPU time = 111 ms,  elapsed time = 331 ms.(25 row(s) affected)Table '#T1_________________________________________________________________________________________________________________000000000009'. Scan count 5, logical reads 59, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table 'Worktable'. Scan count 10731, logical reads 87653, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table '#T3_________________________________________________________________________________________________________________00000000000C'. Scan count 4, logical reads 236, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table '#T2_________________________________________________________________________________________________________________00000000000A'. Scan count 1, logical reads 59, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.(1 row(s) affected) SQL Server Execution Times:   CPU time = 219 ms,  elapsed time = 281 ms.

 

条件 (SELECT COUNT(1) FROM #T2 AS T3 WHERE T3.[object_id]>T1.[object_id])<1 能过滤掉大部分数据,而(SELECT COUNT(1) FROM #T3 AS T2 WHERE T2.column_id>T1.column_id)>1不能过滤任何数据,因此如果优先执行(SELECT COUNT(1) FROM #T3 AS T2 WHERE T2.column_id>T1.column_id)>1,则会大大减少判断(SELECT COUNT(1) FROM #T2 AS T2 WHERE T2.column_id>T1.column_id)>1的次数,从而提高查询速度,但SQL Server无法推断出该结论,因此只能顺序判断WHERE 条件。

 

 

 

总结:虽然在很多情况下SQL Sever引擎能帮助我们判定 WHERE 条件后的执行顺序,但我们仍应该将选择性高(过滤数据多)的条件放置在 WHERE 语句中的前面,尤其对于复杂的SQL 语句,应仔细分析测试。

 

你比SQL SERVER 更了解你的数据!!!

转载地址:http://otghl.baihongyu.com/

你可能感兴趣的文章
使用ipmi调节r410的风扇转速
查看>>
Spring Cloud超简单十分钟入门实例
查看>>
Linux环境Apache2.4+mysql5.7+php5.6快速安装mysql
查看>>
MySql 日常指导,及大表优化思路
查看>>
设计模式之 - 单例模式
查看>>
用 Python 脚本,监听附近网络 Wi-Fi 设备,通过邮件和微信进行消息推送
查看>>
巅峰之证!首位阿里云ACE认证专家产生
查看>>
Spring Cloud Alibaba Sentinel对RestTemplate的支持
查看>>
canvas
查看>>
2018-07-30 到 2018-08-03
查看>>
昨天,我们公司的产品经理被我...
查看>>
【今日头条】【抖音火山】后台开发实习生
查看>>
js文件操作总结一:图片篇
查看>>
外观模式
查看>>
javascript之函数防抖与节流
查看>>
docker 部署前端
查看>>
Spring定时任务的几种实现
查看>>
web前端程序员真的值这么多钱吗?
查看>>
好程序员Java分享JVM结构
查看>>
echarts加轴显示(单位)及标题
查看>>