前段时间遇到一个存储过程,参数之一是一个字符串,在存储过程中,把字符串拆分成一个临时表之后存为一个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作为过滤条件的区别的更多相关文章

  1. 【SQL】查询语句中in和exists的区别

    in in可以分为三类: 一. 形如select * from t1 where f1 in ( &apos:a &apos:, &apos:b &apos:),应该和 ...

  2. 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?

    如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括:如何 ...

  3. 转发:使用sql命令查询视图中所有引用的基础表

    转自:使用sql命令查询视图中所有引用的基础表 使用sql命令查询视图中所有引用的基础表 之前有写过如何利用sql查询视图中所有引用的表发现这个方法并不能查出视图中所有的基础表,如果视图中有嵌套视图就 ...

  4. mysql查询语句中使用星号真的慢的要死?

    前言 之所以写这篇文章,是源于以前看过的关于sql语句优化的帖子,里面明确提到了在sql语句中不要使用 * 来做查询,就像下面的规则中说的 2.尽量避免使用select *,返回无用的字段会降低查询效 ...

  5. SQL逻辑查询语句执行顺序 需要重新整理

    一.SQL语句定义顺序 1 2 3 4 5 6 7 8 9 10 SELECT DISTINCT <select_list> FROM <left_table> <joi ...

  6. SQL Sever查询语句集锦

    一. 简单查询简单的Transact-SQL查询只包括选择列表.FROM子句和WHERE子句.它们分别说明所查询列.查询的表或视图.以及搜索条件等. 例如,下面的语句查询testtable表中姓名为“ ...

  7. python 3 mysql sql逻辑查询语句执行顺序

    python 3 mysql sql逻辑查询语句执行顺序 一 .SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_t ...

  8. mysql第四篇--SQL逻辑查询语句执行顺序

    mysql第四篇--SQL逻辑查询语句执行顺序 一.SQL语句定义顺序 SELECT DISTINCT <select_list> FROM <left_table> < ...

  9. 查询语句中select from where group by having order by的执行顺序

    查询语句中select from where group by having order by的执行顺序   1.查询中用到的关键词主要包含六个,并且他们的顺序依次为  select--from--w ...

随机推荐

  1. stanford corenlp自定义切词类

    stanford corenlp的中文切词有时不尽如意,那我们就需要实现一个自定义切词类,来完全满足我们的私人定制(加各种词典干预).上篇文章<IKAnalyzer>介绍了IKAnalyz ...

  2. [翻译]AKKA笔记 - CHILD ACTORS与ACTORPATH -6

    原文:http://rerun.me/2014/10/21/akka-notes-child-actors-and-path/ Actor是完全的继承结构.你创建的任何Actor肯定都是一个其他Act ...

  3. iOS 开发不可缺少的工具

    1.截屏利器:Snip 强大的滚动截屏功能,你值得拥有! Snip.png 传送门:http://www.snip.qq.com/ 2.Mac上最好的终端模拟器:iTerm2 iTeam.png 传送 ...

  4. 从Fiddler抓包到Jmeter接口测试(简单的思路)

    备注:本文为博主的同事总结的文章,未经博主允许不得转载. Fiddler下载和配置安装 从网上下载fiddler的安装包即可,直接默认,一直点击下一步,直至安装完成. 安装完成后直接打开Fiddler ...

  5. 单例模式——创建型模式01

    1. 名称     单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类.单例模式是一种对象创建型模式. 2. 问题    ...

  6. ASP.NET OWIN OAuth:遇到的2个refresh token问题

    之前写过2篇关于refresh token的生成与持久化的博文:1)Web API与OAuth:既生access token,何生refresh token:2)ASP.NET OWIN OAuth: ...

  7. Java正则速成秘籍(二)之心法篇

    导读 正则表达式是什么?有什么用? 正则表达式(Regular Expression)是一种文本规则,可以用来校验.查找.替换与规则匹配的文本. 又爱又恨的正则 正则表达式是一个强大的文本匹配工具,但 ...

  8. PID控制

    PID解释: 位置式:      可以看出,比例部分只与当前的偏差有关,而积分部分则是系统过去所有偏差的累积.位置式PI调节器的结构清晰,P和I两部分作用分明,参数调整简单明了.但直观上看,要计算第拍 ...

  9. 浏览器加载和渲染HTML的过程(标准定义的过程以及现代浏览器的优化)

    先看一下标准定义的浏览器渲染过程(网上找的): 浏览器打开网页的过程 用户第一次访问网址,浏览器向服务器发出请求,服务器返回html文件: 浏览器开始载入html代码,发现 head 标签内有一个 l ...

  10. php内核分析(一)-sapi_module_struct

    这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux 首先是寻找php的入口,php有很多种模式,apache,php-fpm, cli模式,我要入手的话,只能先从最简单的cl ...