【发布时间】:2017-08-31 03:08:48
【问题描述】:
我的问题解释如下。
这是我现在在我的服务器上运行的 PHP 代码:
$limit = 10000;
$annee = '2017';
//Counting the lines I need to delete
$sql = " SELECT COUNT(*) FROM historisation.cdr_".$annee." a
INNER JOIN transatel.cdr_transatel_v2 b ON a.id_cdr = b.id_cdr ";
$t = $db_transatel->selectAll($sql);
//The number of lines I have to delete
$i = $t[0][0];
do {
if ($i < $limit) {
$limit = $i;
}
//The problem is comming from that delete
$selectFromHistoryAndDelete = " DELETE FROM transatel.cdr_transatel_v2
WHERE id_cdr IN (
SELECT a.id_cdr FROM historisation.cdr_".$annee." a
INNER JOIN (SELECT id_cdr FROM historisation.cdr_transatel_v2) b ON a.id_cdr = b.id_cdr
)
LIMIT " . $limit;
$delete = $db_transatel->exec($selectFromHistoryAndDelete, $params);
$i = $i - $limit;
} while ($i > 0);
如图所示,在前 195 个循环中,执行时间在 13 到 17 秒之间。 第 195 次循环增加到 73 秒,第 196 次循环增加到 1305 秒。
现在查询运行了 2000 秒。
查询正在删除测试表中没有人正确使用的行。
我将第 10,000 行删除 10,000 行,以便查询快速且不会使服务器过载。
我想知道为什么执行时间会这样增加,但我认为最后会更快,因为我认为内部连接会更快,因为它们在表中的行数更少。
有人有想法吗?
编辑:表格引擎是 MyISAM。
【问题讨论】:
-
回滚段。我认为 DB 在某处保留已删除的行以处理可能的回滚。尝试在每次删除后提交。
-
遗憾的是我已经知道了,但是我的表在 MyIASM 中的表中,并且它不支持回滚和提交。
-
当表很大时,IN 太慢了。使用 JOIN 查找要删除的行要快得多。
-
这是因为存储如何与 MyISAM 一起工作。您需要在删除后运行
OPTIMIZE TABLE以回收空闲表空间。实际上,表空间中存在间隙,这些间隙也在处理中。另一种可能的解决方案是切换到 PARTITION 方法。见:stackoverflow.com/a/41252116/1144627 -
一般的想法是加入两个表,如果 ID 为 IN,则其中一个列将具有值,而其他行将在该列中具有 NULL 值。在这种情况下,很容易删除 value IS NOT NULL 的所有行。