慢自我加入删除查询

时间:2011-08-17 05:47:20

标签: sql performance join sql-delete self-join

它比这个查询更简单吗?

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 个答案:

答案 0 :(得分:7)

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

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

  1. 创建一个新表
  2. 只需插入您想要生存的所有记录,
  3. 用新的替换旧的?
  4. 这样的事情可能会更快一点:

    /* 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条记录,则应该相当快。

答案 1 :(得分:0)

运行解释选择a。*来自匹配内连接匹配b ON(a.uid = b.matcheduid)将解释你的索引如何存在和被使用

答案 2 :(得分:0)

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

虽然它很笨拙,但你可以考虑:

一个。创建一个临时表来存储由内连接产生的uid,然后加入到THAT,然后执行删除操作。

OR

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

DELETE * FROM matches WHERE YourBitFlagColumn = True

然后删除布尔列。

答案 3 :(得分:0)

您可能需要批量删除。您可以使用公用表表达式通过递归删除来做到这一点,或仅以一定的批处理大小对其进行迭代。