exists改写SQL,使其走正确的执行计划

数据库环境:SQL SERVER 2005

  今天看到一条SQL,写得不是很复杂,返回7000多条数据,却执行了15s。SQL文本及各表的数据量如下:

SELECT  acinv_07.id_item ,
        SUM(acinv_07.dec_endqty) dec_endqty
FROM    acinv_07
WHERE   acinv_07.fiscal_year * 100 + acinv_07.fiscal_period = ( SELECT DISTINCT
                                                              ctlm1101.fiscal_year
                                                              * 100
                                                              + ctlm1101.fiscal_period
                                                              FROM
                                                              ctlm1101
                                                              WHERE
                                                              flag_curr = ‘Y‘
                                                              AND id_oprcode = ‘acinv‘
                                                              AND acinv_07.id_wh = ctlm1101.id_table
                                                              )
GROUP BY acinv_07.id_item
----------------------------------------
SELECT  COUNT(*)
FROM    ctlm1101
WHERE   flag_curr = ‘Y‘
        AND id_oprcode = ‘acinv‘--26

SELECT  COUNT(*)
FROM    acinv_07--1347176

  我们先看看一下SQL的执行计划

  2个表关联走的是嵌套循环,且大表acinv_07是驱动表,ctlm1101被扫描了1347176次,

ctlm1101.id_table是连接列,且关联后再对acinv_07.fiscal_year * 100 + acinv_07.fiscal_period过滤,

因此,慢是自然的了。

  那我们是否可以改写后,根据原SQL的意思,我们用Exists改写成如下,核对数据无误

SELECT  acinv_07.id_item ,
        SUM(acinv_07.dec_endqty) dec_endqty
FROM    acinv_07
WHERE   EXISTS ( SELECT NULL
                 FROM   ctlm1101
                 WHERE  flag_curr = ‘Y‘
                        AND id_oprcode = ‘acinv‘
                        AND acinv_07.id_wh = ctlm1101.id_table
                        AND ctlm1101.fiscal_year = acinv_07.fiscal_year
                        AND ctlm1101.fiscal_period = acinv_07.fiscal_period )
GROUP BY acinv_07.id_item

  改写之后,执行计划走的是哈希连接,数据一查询是秒出。我们来分析改写后的执行计划,

小表ctlm1101作为哈希连接的驱动表,id_table,fiscal_year,fiscal_period作为连接列,和大表acinv_07

关联时过滤了大部分数据,所以通过哈希匹配可以快速返回所有结果。

时间: 2024-10-22 05:37:31

exists改写SQL,使其走正确的执行计划的相关文章

收集统计信息让SQL走正确的执行计划

数据库环境:SQL SERVER 2005 今天在生产库里抓到一条跑得慢的SQL,语句不是很复杂,返回的数据才有800多行, 却执行了34分钟,甚至更久. 先看一下执行结果 我贴一下SQL. SELECT a.dec_yt1 , b.dec_yt1 , a.dec_yt2 , b.dec_yt2 , a.dec_yt3 , b.dec_yt3 FROM ctlm8288 a , ( SELECT t.corr_id , t.clerk_id , ROUND(SUM(ISNULL(t.dec_yt

SQL Server 性能调优 之执行计划(Execution Plan)调优

执行计划中的三种 Join 策略 SQL Server 存在三种 Join 策略:Hash Join,Merge Join,Nested Loop Join. Hash Join:用来处理没有排过序/没有索引的数据,它在内存中把 Join 两边数据(的关联key)分别建立一个哈希表.例如有以下的查询语句,关联的两张表没有建立索引,执行计划将显示为Hash Join. SELECT sh.* FROM SalesOrdHeaderDemo AS sh JOIN SalesOrdDetailDemo

SQL点滴27—性能分析之执行计划

原文:SQL点滴27-性能分析之执行计划 一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL Server 2008>,有经验的高手尽管拍砖把. 这个部分将讲解一些性能分析工具,这些性能分许主要关注在执行计划. 缓存执行计划  SQL Server 2008提供了一些服务器对象来分析执行计划Sys.dm_exec_cached_plans:    包含缓存

SQL优化--使用 EXISTS 代替 IN 和 inner join来选择正确的执行计划

在使用Exists时,如果能正确使用,有时会提高查询速度: 1,使用Exists代替inner join 2,使用Exists代替 in 1,使用Exists代替inner join例子: 在一般写sql语句时通常会遇到如下语句: 两个表连接时,取一个表的数据,一般的写法通过关联查询(inner join): select a.id, a.workflowid,a.operator,a.stepidfrom  dbo.[[zping.com]]] ainner join workflowbase

oracle表的统计信息完全正确,执行计划无故改变。原厂人员如是回复

就像在电话里提到的那样,Oracle内部的优化器是根据一系列的内部算法基于表上的统计信息来产生执行计划的.对于特别复杂的SQL语句,Oracle的优化器有一定几率不能得到最优的执行计划(因为机器代码实际上是比较死板的,虽然得到的执行计划按照内部的算法来看是比较快的,但是实际上这个执行计划可能在实际执行中比较慢).我们现在碰到的就是这种情况,虽然表的统计信息是准的,但恰恰优化器在基于这个统计信息使用内部算法得到的执行计划是不优化的一这是优化器的固有限制.这时候就需要DBA/Oracle Suppo

SQL Sever 2008性能分析之执行计划

一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试 2的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL Server 2008>,有经验的高手尽管拍砖把. 这个部分将讲解一些性能分析工具,这些性能分许主要关注在执行计划. 缓存执行计划  SQL Server 2008提供了一些服务器对象来分析执行计划Sys.dm_exec_cached_plans:    包含缓存的执行计划,每个执行计划对应一行.Sy

Oracle固定SQL的执行计划(一)---SQL Profile

我们都希望对于所有在Oracle数据库中执行的SQL,CBO都能产生出正确的执行计划,但实际情况却并非如此,由于各种各样的原因(比如目标SQL所涉及的对象的统计信息的不准确,或者CBO内部一些成本计算公式的先天缺陷等),导致有时CBO产生效率不高.甚至是错误的执行计划.特别是CBO对目标SQL所产生的初始执行计划是正确的,后来由于某种原因(比如统计信息的变更等)而导致CBO重新对其产生了错误的执行计划,这种执行计划的改变往往会导致目标SQL执行时间呈数量级的递增,而且常常会让我们很困惑:这个SQ

浅析SQL SERVER执行计划中的各类怪相

在查看执行计划或调优过程中,执行计划里面有些现象总会让人有些疑惑不解: 1:为什么同一条SQL语句有时候会走索引查找,有时候SQL脚本又不走索引查找,反而走全表扫描? 2:同一条SQL语句,查询条件的取值不同,它的执行计划会一致吗? 3: 同一条SQL语句,其执行计划会变化,为什么 4: 在查询条件的某个或几个字段上创建了索引,执行计划就一定会走该索引吗? 5:同时存在几个索引,SQL语句会走那个索引? ..............................................

强制SQL Server执行计划使用并行提升在复杂查询语句下的性能

最近在给一个客户做调优的时候发现一个很有意思的现象,对于一个复杂查询(涉及12个表)建立必要的索引后,语句使用的IO急剧下降,但执行时间不降反升,由原来的8秒升到20秒. 通过观察执行计划,发现之前的执行计划在很多大表连接的部分使用了Hash Join,由于涉及的表中数据众多,因此查询优化器选择使用并行执行,速度较快.而我们优化完的执行计划由于索引的存在,且表内数据非常大,过滤条件的值在一个很宽的统计信息步长范围内,导致估计行数出现较大偏差(过滤条件实际为15000行,步长内估计的平均行数为80