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
关联时过滤了大部分数据,所以通过哈希匹配可以快速返回所有结果。