我想根据主键从中等大小(700K)表中删除大量行。思想,最好的方法应该使用SELECT
- DELETE
源列表的子查询。并找到specific answer here too。问题是:它比使用两个单独的查询慢得多(首先选择ID然后从表中删除这些ID)。为什么会这样?
我也做了简单的测试用例:
CREATE TABLE `xyz` (
`xyzID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`col1` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`xyzID`)
) ENGINE=InnoDB;
用百万条记录填充,然后:
DELETE FROM xyz
WHERE xyzID IN
(
SELECT xyzID
FROM
(
SELECT xyzID
FROM xyz
LIMIT 3000,1000
) a
);
Query OK, 1000 rows affected (53.52 sec)
删除2000行时间加倍:
Query OK, 2000 rows affected (1 min 48.25 sec)
但是没有子查询(首先选择)删除几乎没有时间(在这里随机生成的id-list):
DELETE FROM test.xyz WHERE xyzID IN ( 660422,232794,573802,....
Query OK, 996 rows affected (0.04 sec)
为什么用子查询删除这么慢?
答案 0 :(得分:2)
如果您阅读有关子查询的文档,您会发现一些可能导致此问题的原因: https://dev.mysql.com/doc/refman/5.7/en/subquery-restrictions.html


优化器将使用 exists
将不相关的 WHERE IN(子查询)
语句重写为相关语句。
所以,你的查询实际上可能是这样执行的:


 DELETE FROM xyz t1
 WHERE EXISTS(
(
 SELECT 1&#xA) ; FROM
(
 SELECT xyzID t3
 FROM xyz
 LIMIT 3000,1000
)a
其中t1.xyzID = a.xyzID
);



 现在需要执行相关子查询每次删除单行。

& #xA;因此:对于1000个删除,您将在临时表 a
上运行1000个子查询。
 O内部查询将保持不相关。
与(valuelist)中的相比,您正在运行
1001
查询而不是<代码> 1 代码>
实况:
&#XA;&#XA;&#XA;&# XA;这意味着IN子查询可能比使用IN(value_list)运算符编写的查询慢得多,该运算符列出子查询将返回的相同值。
&#xA;
答案 1 :(得分:0)
子查询意味着您要求您的数据库引擎比较所有&#34; N&#34;第一个表中的行包含所有&#34; M&#34;您正在创建的另一个表中的行。这意味着您有N * M比较操作并且要执行此操作,您需要加入表格。您正在构建的表具有N * M行。
没有子查询,你只是比较所有&#34; N&#34;用&#34; X&#34;表示你的表格中的一行关键词在哪里 &#34; X&#34; &LT;&LT; &#34; M&#34;
答案 2 :(得分:0)
解决此问题的第一步是选择要删除的ID到临时表中。但是,当您尝试实际执行删除操作时,仍然可能会遇到慢子查询的问题。
解决方案是使用DELETE xyz FROM xyz INNER JOIN xyz_temp WHERE xyz.id = xyz_temp.id
语法,该语法可以实现相同的功能,并且运行速度与简单的联接一样快。