你的位置:首页 > 数据库

[数据库]exists改写SQL,使其走正确的执行计划


数据库环境:SQL SERVER 2005

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

SELECT acinv_07.id_item ,    SUM(acinv_07.dec_endqty) dec_endqtyFROM  acinv_07WHERE  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  ctlm1101WHERE  flag_curr = 'Y'    AND id_oprcode = 'acinv'--26    SELECT COUNT(*)FROM  acinv_07--1347176

View Code

  我们先看看一下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_endqtyFROM  acinv_07WHERE  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

View Code

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

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

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