是否可以更快地加入where子句,或者之后删除行?

时间:2014-06-06 16:13:52

标签: mysql

好的,所以我将一些数据从另一个连接中加载到表中(如果ts是时间戳列):

insert ignore into target_table select s.user_id,i.item_id,i.artist_id,s.ts 
from source_table s join itemlist i on s.item_url = i.item_url;

问题是,我只想要在一定时间范围内来自内部的数据,所以我的问题是:用连接中的where子句来做这个会更快,即:

insert ignore into target_table select s.user_id,i.item_id,i.artist_id,s.ts 
from source_table s join itemlist i on s.item_url = i.item_url where 
ts< '2013-01-01' and ts >= '2005-07-01';

或者,要进行第一次查询,然后进行删除,即:

delete from target_table where ts>= '2013-01-01' and ts < '2005-07-01';

我知道我可以自己测试一下,但我也想了解为什么首选一种方法

2 个答案:

答案 0 :(得分:1)

第一个版本应该更快:

insert ignore into target_table(user_id, item_id, artis_it, ts)
    select s.user_id,i.item_id,i.artist_id,s.ts 
    from source_table s join
         itemlist i
         on s.item_url = i.item_url
    where ts < '2013-01-01' and ts >= '2005-07-01';

以下是一些原因:

  • 由于运行命令的开销,执行一个命令而不是多个命令会更快。
  • 每个插入都有开销(记录,将记录复制到数据页,分配数据页)。执行不必要的插入需要的时间超过必要时间。
  • 每次删除都有开销(记录,解除分配页面)。
  • 插入和删除可能包含会导致更多开销的触发器。
  • 在插入和删除之间,表中的数据不准确。

答案 1 :(得分:1)

(假设你的意思是第二个方法的WHERE子句实际上与第一个方法相反 - 否则你最终会得到不同的结果......)

它取决于表上的索引以及表中的数据量。

如果两个表都在ts上有一个索引,那么我看不出它会产生差异很多,性能方面,假设行数不多,但它会更常见的是限制初始SELECT,因此您只执行一次操作。

表格中的数据量是相关的。想想这个例子:source_table中有十亿行,但只有一行符合您的条件。在这种情况下,带有SELECT子句的索引WHERE将非常快速地找到该行并将其复制到目标表中。但是,第二种方法会将十亿行复制到目标表,这将耗费很长时间(以及大量磁盘空间),然后您只需删除其中一行,这可能需要相当长的时间如果发现你要保留的行因索引而非常快。

插入然后删除也可能导致目标表中更多“碎片化”的数据,但这可能取决于存储引擎,我不太了解MySQL如何处理这样的事情来发表意见。

要记住的其他事项:如果您INSERT然后DELETE,则会有一段时间表中的数据“错误”。如果你没有包含在交易中并且INSERTDELETE之间出现问题,那么它可能会出错。如果您只使用INSERT执行WHERE,那么这是一个atomic操作,可以完全成功或回滚。