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

where

a.column2 between @paramater1 and @parameter2

第二种是将这个过滤条件放在where 条件中

select * from tableA a inner join tableB b on a.id=b.id

where

a.column between @paramater1 and @parameter2

and b.key in (select key from #t)

实际上这个存储过程本身比较复杂,十多张表的一个复杂的join和多钟过滤逻辑,其中有几张大表将近千万级,核心点的不同在于类似上面查询条件的处理方式,

本身的逻辑是用第一种方式去实现的,一开始把重点放在索引,统计信息之类上面,怎么也找不到原因

发现在性能很差,本身这里我只是举一个简单的例子,实际上很难去模拟实际的逻辑

这个问题困惑了我好久,

一开始没想到原因在于上述的用inner join中间结果集的方式过滤和直接放在where 条件中的区别,

后来仔细观察执行计划,发现第一种方式的执行计划是这样的:

执行计划最开始对物理表做过滤的时候,没有先用#t中的值去过滤物理表,仅仅用TableA上column2 的过滤条件得到一个结果集,然后用这个较大的结果集去驱动其他表,最后再去跟#t做join,

等于是中间结果集非常大,最后才去跟#t做join过滤,性能上比较差

其实一直以来没意识到时上述inner join #t造成的,一开始是对索引,统计信息之类的做各种优化,都没有得到怎么改善

后来换成第二种方式,对于物理表的处理是这样的:用上column2 和 #t共同去过滤TableA,等到一个中间结果集,然后去驱动其他的表

生成的图形化的执行计划,估计两屏都显示不下,通过一步一步的观察,看了好久,才发现是这个差别,

虽然最后的结果是一样的,但是这个查询的效率差别非常大,因为一开始对TableA过滤的时候,得到的是一个比较小的结果,后面再去驱动其他表或者是跟其他表join,代价都比较小

这个问题困惑了好多天,本来想自己写个demo验证一下的,无奈实际场景太复杂了,很难模拟出那种数据和表之间的逻辑关系。

不过可以明确的是,上述写法,对于简单的demo,可能性能上区别不大,但是执行计划的差别还是很明显的

以后优化sql的时候,多个思路,尤其是在复杂的条件下,面对查询条件的处理方式,一定要慎重

时间: 2024-10-10 02:32:26

SQL优化 查询语句中,用 inner join 作为过滤条件和用where作为过滤条件的区别的相关文章

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

如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括:如何在SQL Server存储过程中获取另一存储过程的执行结果记录集?如何在存储过程中检索动态SQL语句的执行结果?如何实现类似SELECT * FROM (EXEC procedure_name @parameters_var) AS datasource ... 的功能?procedure_

Sql 查询语句中的类型转换

1: CAST ( (SalesAgreement.HTPrice / 10000) as decimal(18,2) ) as HTPrice 2: 转换货币如:10,000.00 select '¥'+convert(nvarchar,cast(1343432432434.8 as money),1) Sql 查询语句中的类型转换

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

转自:使用sql命令查询视图中所有引用的基础表 使用sql命令查询视图中所有引用的基础表 之前有写过如何利用sql查询视图中所有引用的表发现这个方法并不能查出视图中所有的基础表,如果视图中有嵌套视图就会有问题,因为目录视图sys.sql_dependencies并不包含所有的引用实体.后面发现在sql2008及以后的版本中推出的sys.sql_expression_dependencies视图解决了这一问题,所以重新写了段sql,用来查询视图中所有引用的基础表,包括嵌套视图中的基础表.这个有什么

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

前言 之所以写这篇文章,是源于以前看过的关于sql语句优化的帖子,里面明确提到了在sql语句中不要使用 * 来做查询,就像下面的规则中说的 2.尽量避免使用select *,返回无用的字段会降低查询效率.如下: SELECT * FROM t 优化方式:使用具体的字段代替*,只返回使用到的字段. 但是中国有句姥话叫“尽信书不如无书”,难道在sql查询语句中使用星号就真的慢的要死,难道加索引也不行?带着这些个疑问,我进行了一些测试.结果发现,江湖传说未必真的靠得住.那具体测试情况是咋样的呢?下面且

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

python 3 mysql sql逻辑查询语句执行顺序 一 .SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> WHERE <where_condition> GROUP BY <group_by_list> HAVING <havin

MySQL 抓取SQL慢查询语句

当MySQL服务器出现异常(慢),首先要考虑是否因,SQL语句引起数据库慢,如果情况比较紧急,我们就要立刻 SHOW FULL PROCESSLIST; 去查看,但我建议大家使用-e参数,采用非交互的方式,因为这样可以使用grep等命令,对结果进行过滤,更方便直观的看到结果 一.抓SQL慢查询语句的方法,有2种: 1,临时紧急抓取 通过SHOW FULL PROCESSLIST; 的方式,执行几次,有相同语句,就可能是SQL慢查询语句: SHOW FULL PROCESSLIST; #查看MyS

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

mysql第四篇--SQL逻辑查询语句执行顺序 一.SQL语句定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> WHERE <where_condition> GROUP BY <group_by_list> HAVING <having_condition&g

IQueryable 查询语句中 OrderByDescending() 扩展方法使用注意点

目的: 查询结构物下所有网关的最新诊断结果. 1. 正确查询 (按诊断时间倒序) var query = queryDiag.GroupBy(g => new {g.dtuId, g.dtuNo, g.dtuDesp}) .Select(s => s.GroupBy(r => r.diagTime) .Select(e => new { s.Key.dtuId, s.Key.dtuNo, s.Key.dtuDesp, diagTime = e.Key, cpuRatio = e.W

SQL复杂查询语句-SELECT * FROM cs WHERE score&gt;70 GROUP BY s_id HAVING COUNT(*)&gt;1

如果同时存在where,group by,的时候的执行顺序应该是这样的: 1,首先where后面添加条件把数据进行了过滤,返回一个结果集 2,然后group by将上面返回的结果集进行分组,返回一个结果集 3,然后having将上面分组好了的结果集进行再次过滤,返回最后的结果集 4,select开始查询结果集 查询语句中select from where group by having order by的执行顺序 1.查询中用到的关键词主要包含六个,并且他们的顺序依次为 select--from