删除除一个优化查询之外的所有重复项

时间:2013-11-21 18:55:09

标签: mysql sql

我尝试了以下两个查询:

delete from app where not exists
(select a2.app_package, max(a2.id) from (select * from app) as a2
 where a2.app_package = app.app_package having max(a2.id) = app.id);

DELETE FROM app
USING app, 
(select app_package, max(id) as ID from app
group by app_package
) as A 
where A.ID > app.ID AND
A.app_package = app.app_package;

我真的很担心哪一个会执行得更快。

SQLFiddles:

两个执行计划都是相同的:

ID  SELECT_TYPE TABLE   TYPE    POSSIBLE_KEYS   KEY KEY_LEN REF ROWS    FILTERED    EXTRA
1    SIMPLE    app    ALL                                        7    100

是否可以进一步优化?

1 个答案:

答案 0 :(得分:2)

您正在显示的执行计划不是DELETE查询的执行计划,而是来自SELECT * FROM app查询的执行计划,它只执行全表扫描(正如您未对任何内容进行过滤所预期的那样)。

要查看执行计划,您需要在delete语句上运行说明(在sqlfiddle中显然不可能)。

我冒昧地假设你在app_package上有一个索引。如果你不这样做,你一定要添加它。

第一个例子(简单地用SELECT * FROM替换DELETE FROM)表明你正在进行全表扫描(坏)并使用一个DEPENDENT子查询,该子查询将为外表中的几乎每个记录运行(这也很糟糕) )。

1   PRIMARY app ALL 7   Using where
2   DEPENDENT SUBQUERY  <derived3>  ALL 7   Using where
3   DERIVED app ALL 7   

要查看第二个,您必须将删除转换为SELECT语句,类似这样

SELECT * FROM app, (
SELECT app_package, MAX( id ) AS ID
FROM app
GROUP BY app_package
) AS A
WHERE A.ID > app.ID
AND A.app_package = app.app_package

给出了

1   PRIMARY <derived2>  ALL 4   
1   PRIMARY app ref 1   Using where
2   DERIVED app index   7   

正如您所看到的,这是一个不使用从属子查询而不进行全表扫描。当表中的数据量增长时,这肯定会更快。