Sql 慢速自连接删除查询
它比这个查询简单吗Sql 慢速自连接删除查询,sql,performance,join,sql-delete,self-join,Sql,Performance,Join,Sql Delete,Self Join,它比这个查询简单吗 delete a.* from matches a inner join matches b ON (a.uid = b.matcheduid) 是的,显然是这样。。。因为当匹配表非常大时,上述查询的性能非常差 匹配项约为2.2亿条记录。我希望这个删除查询将记录的大小减少到15000条左右。如何提高查询的性能?我在两列上都有索引。UID和MatchedUID是此InnoDB表中仅有的两列,它们的类型都是INT(10)unsigned。查询在我的笔记本电脑(i7处理器
delete a.* from matches a
inner join matches b ON (a.uid = b.matcheduid)
是的,显然是这样。。。因为当匹配
表非常大时,上述查询的性能非常差
匹配项约为2.2亿条记录。我希望这个删除查询将记录的大小减少到15000条左右。如何提高查询的性能?我在两列上都有索引。UID和MatchedUID是此InnoDB表中仅有的两列,它们的类型都是INT(10)unsigned。查询在我的笔记本电脑(i7处理器)上运行了14个多小时。运行解释选择a.*从匹配a的内部联接匹配b的(a.uid=b.matcheduid)将解释索引的存在和使用方式。运行解释选择a.*从匹配a的内部联接匹配b的(a.uid=b.matcheduid)我想解释一下你的索引是如何存在和使用的删除这么多记录可能需要一段时间,我认为如果你这样做的话,这是最快的。如果您不想投资更快的硬件,我建议另一种方法:
如果确实要删除2.2亿条记录,那么表中只剩下15000条记录,这大约占所有条目的99999%。为什么不呢
创建一个新表
只需插入所有你想保存的记录
把你的旧的换成新的
类似这样的方法可能会更快一些:
/* 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;
在此之后,您只需检查并创建所需的索引,如果只处理15000条记录,则索引速度应该相当快。删除这么多记录可能需要一段时间,我认为这样做的速度与这样做的速度一样快。如果您不想投资更快的硬件,我建议另一种方法:
如果确实要删除2.2亿条记录,那么表中只剩下15000条记录,这大约占所有条目的99999%。为什么不呢
创建一个新表
只需插入所有你想保存的记录
把你的旧的换成新的
类似这样的方法可能会更快一些:
/* 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;
在此之后,您只需检查并创建所需的索引,如果只处理15000条记录,这应该是相当快的。我可能会在这里设置自己,但在自连接过程中执行这样的删除操作,不是吗;查询在每次删除后是否必须重新计算联接索引
虽然它是笨拙的蛮力,你也可以考虑:
A.创建一个临时表来存储内部连接产生的uid,然后连接到该表,然后执行删除
或
B.添加一个布尔(位)类型的列,使用连接标记每个匹配项(此操作应快速),然后使用:
DELETE * FROM matches WHERE YourBitFlagColumn = True
然后删除布尔列。我可能会在这里设置自己被烤熟,但在自连接过程中执行这样的删除操作,不是吗;查询在每次删除后是否必须重新计算联接索引
虽然它是笨拙的蛮力,你也可以考虑:
A.创建一个临时表来存储内部连接产生的uid,然后连接到该表,然后执行删除
或
B.添加一个布尔(位)类型的列,使用连接标记每个匹配项(此操作应快速),然后使用:
DELETE * FROM matches WHERE YourBitFlagColumn = True
然后删除布尔列。您可能需要批量删除。您可以通过使用公共表表达式的递归删除来执行此操作,也可以在某个批处理大小上对其进行迭代。您可能需要对删除进行批处理。您可以通过使用公共表表达式进行递归删除来实现这一点,也可以在某个批处理大小上对其进行迭代。愚蠢的想法:使用SELECT
可以更快地解决问题吗?如果是这样,请创建一个包含要删除的ID的临时表,然后连接该表或在(子查询)
中使用,看看这是否更快。其他愚蠢的想法:这些列上有索引吗?是的,两列上都有索引。也许这就是删除速度慢的原因@丹-我试试你的建议。愚蠢的想法:用选择会更快解决问题吗?如果是这样,请创建一个包含要删除的ID的临时表,然后连接该表或在(子查询)
中使用,看看这是否更快。其他愚蠢的想法:这些列上有索引吗?是的,两列上都有索引。也许这就是删除速度慢的原因@丹-我试试你的建议。这几乎是不需要动脑筋的。完美的答案!查询完成后,我会通知您。希望不会花太长时间。:)@是的,嗯?我是这样想的,因为我想念森林,这很好。我去睡觉了,所以不知道花了多长时间,但这肯定是一个进步@XIV解决方案-我应该知道是删除让我慢了下来(因为索引)。检查NULL时的左外连接正是我想要的,但我想不出来。有时候很令人沮丧,对吧?这几乎是不需要动脑筋的。完美的答案!查询完成后,我会通知您。希望不会花太长时间。:)@是的,嗯?我是这样想的,因为我想念森林,这很好。我去睡觉了,所以不知道花了多长时间,但这肯定是一个进步@XIV解决方案-我应该知道是删除让我慢了下来(因为索引)。检查NULL时的左外连接正是我想要的,但我想不出来。有时会令人沮丧,对吧?这可能会起作用,但至少给出穹顶类的示例或链接会有所帮助。这可能会起作用,但至少给出穹顶类的示例或链接会有所帮助。