当前位置: 代码迷 >> Sql Server >> 怎么在 delete 中优化 not exists
  详细解决方案

怎么在 delete 中优化 not exists

热度:916   发布时间:2016-04-24 10:07:54.0
如何在 delete 中优化 not exists
原SQL:

DELETE 
FROM   [u]
WHERE  dbId = 2
       AND NOT EXISTS (
               SELECT 1
               FROM   temp t
               WHERE  t.dbId = 2
                      AND t.tableId = 3
                      AND [u].[id] = CONVERT(BIGINT, t.pkId)
           )

对于这种形式的sql, 有办法优化吗?这条语句要执行一个小时,而删除条件换成 Exists 执行则只需要几秒……
in 就更不消说了, 更慢……

网上找了一下, 据说什么 merge, except 可以代替, 但公司用的环境偏是 2005 , 难道就真的没有办法了吗?


------解决方案--------------------
not exists换成 left outer join应该会很快。
------解决方案--------------------
DELETE [u]
FROM [u] left join
     temp t on t.dbId = 2 AND t.tableId = 3 AND [u].[id] = CONVERT(BIGINT, t.pkId)
WHERE [u].dbId = 2

,还有可以试试先在表设计里,把temp表的pkId改成BIGINT类型,减少类型转换消耗
------解决方案--------------------
既然 EXISTS 很快可以试试下面这样。
特别适合 temp 很大的时候,和 u 表 join 起来后中间表太大的情况。
INSERT INTO #T
SELECT id, 1 AS DeleteFlag
  FROM [u]
 WHERE dbId = 2;

UPDATE #T
   SET DeleteFlag = 0
 WHERE EXISTS (
               SELECT 1
               FROM   temp t
               WHERE  t.dbId = 2
                      AND t.tableId = 3
                      AND #T.id = CONVERT(BIGINT, t.pkId)
           );
 
DELETE [u]
FROM   [u], #T
WHERE  [u].dbId = 2
  AND  [u].id = #T.id
  AND  #T.DeleteFlag = 1

------解决方案--------------------
引用:


其实在你发贴之前, 我也用了类似的方法, 速度确实快了很多。

真正慢的原因也找到了:索引碎片率非常大

建议:
 1.设定SQL维护计划,定期针对大表重整或重建索引.
 2.确认数据库属性中自动更新统计信息已启用.
 3.查看执行计划,看什么环结执行成本较高,针对性的解决.
  相关解决方案