SQL优化 查询语句中,用 inner join 作为过滤条件和用where作为过滤条件的区别
前段时间遇到一个存储过程,参数之一是一个字符串,在存储过程中,把字符串拆分成一个临时表之后存为一个key值的临时表,作为其中一个查询条件,
逻辑实现上有两种处理方式
insert into #t
select key from split_function('传递进来的字符串',',')
第一种是与物理表做inner join,类似如下
select *
from tableA a
inner join tableB b on a.id = b.id
inner join #t c on b.key=c.key
inner join otherTables d on a.id=d.id
where a.column2 between @paramater1 and @parameter2
and other query condition
第二种是将这个过滤条件放在where 条件中
select *
from tableA a
inner join tableB b
on a.id = b.id
inner join otherTables c on a.id=c.id
where a.column between @paramater1 and @parameter2
and b.key in (select key from #t)
and other query condition
实际上这个存储过程本身比较复杂,十多张表的一个复杂的join和多钟过滤逻辑,其中有几张大表将近千万级,核心点的不同在于类似上面查询条件的处理方式,
本身的逻辑是用第一种方式去实现的,因为有较大的性能问题,一开始把重点放在索引,统计信息之类上面,怎么也找不到原因
发现在性能始终很差,上面我只是举一个简单的例子,实际情况远远比上面复杂,上很难去模拟实际的逻辑
这个问题困惑了我好久,
因为当时没意识到上述第一种写法下的用inner join中间结果集的方式过滤和直接放在where 条件中的区别,
后来仔细观察执行计划,发现第一种方式的执行计划是这样的:
执行计划最开始对物理表做过滤的时候,没有先用#t中的值去过滤物理表,仅仅用TableA上column2 的过滤条件得到一个结果集,然后用这个较大的结果集去驱动其他表,最后再去跟#t做join,
等于是中间结果集非常大,最后才去跟#t做join过滤,性能上比较差
由于当时以来没意识到时上述inner join #t的方式造成的,把问题集中在索引上,对索引,统计信息之类的做各种分析优化,都没有得到怎么改善
后来换成第二种方式,效率提高了很多,
生成的图形化的执行计划,估计两屏都显示不下,通过一步一步的观察,
看了好久,才发现是两种方式的差别在于这里:
对于物理表的处理是这样的:用上column2 和 #t 与TABLEB的结果共同去过滤TableA,得到一个中间结果集,然后去驱动其他的表
虽然最后的结果是一样的,但是这个查询的效率差别非常大,因为一开始对TableA过滤的时候,得到的是一个比较小的结果,后面再去驱动其他表或者是跟其他表join,
由于这里生成的中间结果集事先利用了#t的过滤条件,所以中间结果集比较小,
因此后继跟其他表join起来,整体代价比较小,性能上有一个较大的提升
这个问题困惑了好多天,本来想自己写个demo验证一下的,无奈实际场景太复杂了,很难模拟出那种数据和表之间的逻辑关系。
不过可以明确的是,上述写法,对于简单的demo,可能性能上区别不大,但是执行计划的差别还是很明显的,对于复杂的情况,可能就要具体分析了
以后优化sql的时候,多个思路,尤其是在复杂的条件下,面对查询条件的处理方式,是否有必要用inner join的方式达到过滤数据的目的,一定要慎重
最后上两个简单的demo,看一下执行计划的区别,实际情况是在是模拟不出来,只能这样通过执行计划看一下两者之间的区别
(本文不讨论索引,仅仅在相同的表结构情况下,从执行计划差异的角度来看问题的)
SQL优化 查询语句中,用 inner join 作为过滤条件和用where作为过滤条件的区别的更多相关文章
- 【SQL】查询语句中in和exists的区别
in in可以分为三类: 一. 形如select * from t1 where f1 in ( &apos:a &apos:, &apos:b &apos:),应该和 ...
- 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?
如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括:如何 ...
- 转发:使用sql命令查询视图中所有引用的基础表
转自:使用sql命令查询视图中所有引用的基础表 使用sql命令查询视图中所有引用的基础表 之前有写过如何利用sql查询视图中所有引用的表发现这个方法并不能查出视图中所有的基础表,如果视图中有嵌套视图就 ...
- mysql查询语句中使用星号真的慢的要死?
前言 之所以写这篇文章,是源于以前看过的关于sql语句优化的帖子,里面明确提到了在sql语句中不要使用 * 来做查询,就像下面的规则中说的 2.尽量避免使用select *,返回无用的字段会降低查询效 ...
- SQL逻辑查询语句执行顺序 需要重新整理
一.SQL语句定义顺序 1 2 3 4 5 6 7 8 9 10 SELECT DISTINCT <select_list> FROM <left_table> <joi ...
- SQL Sever查询语句集锦
一. 简单查询简单的Transact-SQL查询只包括选择列表.FROM子句和WHERE子句.它们分别说明所查询列.查询的表或视图.以及搜索条件等. 例如,下面的语句查询testtable表中姓名为“ ...
- python 3 mysql sql逻辑查询语句执行顺序
python 3 mysql sql逻辑查询语句执行顺序 一 .SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_t ...
- mysql第四篇--SQL逻辑查询语句执行顺序
mysql第四篇--SQL逻辑查询语句执行顺序 一.SQL语句定义顺序 SELECT DISTINCT <select_list> FROM <left_table> < ...
- 查询语句中select from where group by having order by的执行顺序
查询语句中select from where group by having order by的执行顺序 1.查询中用到的关键词主要包含六个,并且他们的顺序依次为 select--from--w ...
随机推荐
- Redis学习手册(目录)
为什么自己当初要选择Redis作为数据存储解决方案中的一员呢?现在能想到的原因主要有三.其一,Redis不仅性能高效,而且完全免费.其二,是基于C/C++开发的服务器,这里应该有一定的感情因素吧.最后 ...
- iOS开发的知名大牛博客小汇
王巍的博客:王巍目前在日本横滨任职于LINE.工作内容主要进行Unity3D开发,8小时之外经常进行iOS/Mac开发.他的陈列柜中已有多款应用,其中番茄工作法工具非常棒.http://onevcat ...
- ASP.NET MVC系列:Area
1. Area简介 ASP.NET MVC Area机制构建项目,可以将相对独立的功能模块切割划分,降低项目的耦合度. 2. Area设置Routing 新建Admin Area后,自动创建Admin ...
- 4. SVM分类器求解(2)
最优间隔分类器(optimal margin classifier) 重新回到SVM的优化问题: 我们将约束条件改写为: 从KKT条件得知只有函数间隔是1(离超平面最近的点)的线性约束式前面的系数,也 ...
- Hawk 3. 网页采集器
1.基本入门 1. 原理(建议阅读) 网页采集器的功能是获取网页中的数据(废话).通常来说,目标可能是列表(如购物车列表),或是一个页面中的固定字段(如JD某商品的价格和介绍,在页面中只有一个).因此 ...
- angular2系列教程(四)Attribute directives
今天我们要讲的是ng2的Attribute directives.顾名思义,就是操作dom属性的指令.这算是指令的第二课了,因为上节课的components实质也是指令. 例子
- Handler系列之内存泄漏
本篇简单的讲一下平常使用Handler时造成内存泄漏的问题. 什么是内存泄漏?大白话讲就是分配出去的内存,回收不回来.严重会导致内存不足OOM.下面来看一下造成内存泄漏的代码: public clas ...
- 分布式系统理论基础 - CAP
引言 CAP是分布式系统.特别是分布式存储领域中被讨论最多的理论,“什么是CAP定理?”在Quora 分布式系统分类下排名 FAQ 的 No.1.CAP在程序员中也有较广的普及,它不仅仅是“C.A.P ...
- DotNet程序配置文件
在实际的项目开发中,对于项目的相关信息的配置较多,在.NET项目中,我们较多的将程序的相关配置直接存储的.config文件中,例如web.config和app.config. .NET中配置文件分为两 ...
- golang枚举类型 - iota用法拾遗
在c#.java等高级语言中,经常会用到枚举类型来表示状态等.在golang中并没有枚举类型,如何实现枚举呢?首先从枚举的概念入手. 1.枚举类型定义 从百度百科查询解释如下:http://baike ...