我想找到在~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
答案 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,它将运行该查询。