1

它比这个查询更简单吗?

delete a.* from matches a
    inner join matches b ON (a.uid = b.matcheduid)

是的,显然确实如此......因为当matches表非常大时,上述查询的性能非常糟糕。

matches大约有 2.2 亿条记录。我希望这个 DELETE 查询将大小减少到大约 15,000 条记录。如何提高查询的性能?我在两列都有索引。UID 和 MatchedUID 是这个 InnoDB 表中仅有的两列,两者都是无符号的 INT(10) 类型。该查询在我的笔记本电脑(i7 处理器)上运行了 14 多个小时。

4

4 回答 4

7

删除这么多记录可能需要一段时间,我认为如果你这样做的话,这是最快的。如果你不想投资更快的硬件,我建议另一种方法:

如果你真的想删除 2.2 亿条记录,那么该表只剩下 15.000 条记录,这大约是所有条目的 99,999%。为什么不

  1. 创建一个新表,
  2. 只需插入您想要生存的所有记录,
  3. 并用新的替换旧的?

像这样的东西可能会更快一点:

/* creating the new table */
CREATE TABLE matches_new
SELECT a.* FROM matches a
LEFT JOIN matches b ON (a.uid = b.matcheduid)
WHERE ISNULL (b.matcheduid)

/* renaming tables */
RENAME TABLE matches TO matches_old;
RENAME TABLE matches_new TO matches;

在此之后,您只需检查并创建所需的索引,如果只处理 15.000 条记录,这应该会相当快。

于 2011-08-17T06:00:26.597 回答
0

运行 explain select a.* from matches a inner join matches b ON (a.uid = b.matchuid) 将解释您的索引是如何存在和使用的

于 2011-08-17T06:00:00.497 回答
0

我可能会将自己设置为在这里烤,但是在自连接过程中执行这样的删除操作时,查询是否必须在每次删除后重新计算连接索引?

虽然它笨重且蛮力,但您可以考虑:

A. 创建一个临时表来存储内部连接产生的 uid,然后加入到那个,然后执行删除。

或者

B. 添加一个布尔(位)类型的列,使用连接来标记每个匹配项(此操作应该是 FAST),然后使用:

DELETE * FROM matches WHERE YourBitFlagColumn = True

然后删除布尔列。

于 2011-08-17T06:01:53.717 回答
0

您可能需要批量删除。您可以使用公用表表达式通过递归删除来执行此操作,或者只是在某个批量大小上对其进行迭代。

于 2020-08-28T21:14:05.830 回答