我尝试了以下两个查询:
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
答案 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
正如您所看到的,这是一个不使用从属子查询而不进行全表扫描。当表中的数据量增长时,这肯定会更快。