MySQL在JOIN和IN之间的性能差异

时间:2013-08-06 16:02:04

标签: mysql

我想找到在~5米行表中有后继的所有小时记录。

我试过了:

SELECT DISTINCT (date_time)
FROM my_table
JOIN (SELECT DISTINCT (DATE_ADD( date_time, INTERVAL 1 HOUR)) date_offset
      FROM my_table) offset_dates
ON date_time = date_offset

SELECT DISTINCT(date_time)
FROM my_table
WHERE date_time IN (SELECT DISTINCT(DATE_ADD(date_time, INTERVAL 1 HOUR))
                    FROM my_table)

第一个在几秒钟内完成,秒数持续数小时。 我可以理解,越快越好,但为什么会有这么大的性能差距?

--------编辑---------------

以下是两个查询的EXPLAIN

id  select_type table       type    possible_keys   key     key_len ref                         rows    Extra
1   PRIMARY     <derived2>  ALL     NULL            NULL    NULL    NULL                        1710    Using temporary
1   PRIMARY     my_table    ref     PRIMARY         PRIMARY 8       offset_dates.date_offset    555     Using index
2   DERIVED     my_table    index   NULL            PRIMARY 13      NULL                        5644204 Using index; Using temporary


id  select_type        table    type    possible_keys   key     key_len ref     rows    Extra
1   PRIMARY            my_table range   NULL            PRIMARY 8       NULL    9244    Using where; Using index for group-by
2   DEPENDENT SUBQUERY my_table index   NULL            PRIMARY 13      NULL    5129983 Using where; Using index; Using temporary

4 个答案:

答案 0 :(得分:2)

我会在explain之前为两个查询添加前缀,然后比较访问计划中的差异。您可能会发现第一个查询的行数远远少于第二个查询。

但我的预感是JOIN的应用比WHERE子句更直接。因此,在WHERE子句中,您将从my_table获取每个记录,应用算术函数,然后对它们进行排序,因为select distinct通常需要排序,有时它会在内存或磁盘上创建临时表。检查的行数可能是每个表大小的乘积。

但是在JOIN子句中,很多正在WHERE子句中检查和排序的行可能会事先被删除。你最终可能会看到更少的行...而数据库可能需要更容易的措施来完成它。

但我认为这篇文章最能回答你的问题:SQL fixed-value IN() vs. INNER JOIN performance

答案 1 :(得分:2)

通常,使用连接的查询将比使用IN (...)的等效查询执行得更好,因为前者可以利用索引,而后者则不能;必须针对可能返回的每一行扫描整个IN列表。

(请注意,在这种情况下,某些数据库引擎的性能优于其他数据库;例如,SQL Server can produce equivalent performance for both types of queries。)

通过将SELECT添加到查询并运行它,您可以查看MySQL查询优化器打算如何处理给定的EXPLAIN查询。除其他外,这将为您提供引擎必须检查查询中每个步骤的行数。将这些计数相乘得到引擎必须访问的总行数,这可以作为对可能性能的粗略估计。

答案 2 :(得分:1)

'IN'子句对于大型表来说通常很慢。据我记得,对于你打印出的第二个语句 - 它将简单地循环遍历my_table的所有行(除非你有索引)检查每一行以匹配WHERE子句。通常,IN被视为一组包含所有set元素的OR子句。 这就是为什么我认为使用在JOIN查询后台创建的临时表更快。

以下是一些有用的链接:

MySQL Query IN() Clause Slow on Indexed Column

inner join and where in() clause performance?

http://explainextended.com/2009/08/18/passing-parameters-in-mysql-in-list-vs-temporary-table/

答案 3 :(得分:1)

另外需要考虑的是,使用IN风格,与JOIN相比,未来的优化很少。通过连接,您可以添加一个索引,谁知道,它取决于数据集,它可能会加快速度提高2倍,5倍,10倍。使用IN,它将运行该查询。