我有两张桌子。在表格 UnRevisedTable 中输入原始数据,在表格 RevisedTable 中,只有人类在 UnRevisedTable中找到值时插入的修订值条目强烈>比他不喜欢。
在 UnRevisedTable 中,每分钟都有一个条目,在 RevisedTable 中, UnRevisedTable 中的每个不需要的条目都有一个条目。
这两个查询的目的是相同的:在修订数据时,向我展示修订数据和未修改数据的联合,以替换未经修改的数据。
我开始编写query2但它太慢了。然后我写了query1,查询1更快,更快。
我的问题是为什么query1比query2更快? THX。
query1:
SELECT o.start_date_time,
CASE WHEN r.start_date_time IS NULL THEN o.value ELSE r.value END AS value,
FROM UnRevisedTable o LEFT JOIN RevisedTable r ON o.start_date_time = r.start_date_time
WHERE o.start_date_time >= '".$start."' AND o.start_date_time < '".$finish."' ORDER BY start_date_time ASC;
query2:
select * from(
select RevisedTable.* from RevisedTable where start_date_time between '".$start."' and '".$finish."'
union
select UnRevisedTable.* from UnRevisedTable where start_date_time between '".$start."' and '".$finish."'
) as t1 group by start_date_time;
这里提到的Abhik Chakraborty是解释query1并解释query2:
QUERY1:
+----+-------------+-------+--------+---------------+---------+---------+------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+------------------------+------+-------------+
| 1 | SIMPLE | o | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 8 | Mydb.o.start_date_time | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+------------------------+------+-------------+
QUERY2:
+----+--------------+------------+-------+---------------+---------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+---------------+---------+---------+------+------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 14 | Using temporary; Using filesort |
| 2 | DERIVED | RevisedTable | range | PRIMARY | PRIMARY | 8 | NULL | 2 | Using where |
| 3 | UNION | UnRevisedTable| range | PRIMARY | PRIMARY | 8 | NULL | 10 | Using where |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+------------+-------+---------------+---------+---------+------+------+---------------------------------+
答案 0 :(得分:2)
首先,这两个查询不会做同样的事情。
UnrevisedTable
的时间。如果RevisedTable
中的某些时间不在Unrevised
,则您将无法获得它们。join
。并且,如果您在连接键start_date_time
上有索引,那么将使用索引。聚合不太可能使用索引。value
。 第二个查询正在进行两次聚合,但没有连接。第一个聚合用于删除重复值(对于union
),第二个聚合用于删除外部group by
。
我首先修改第二个查询:
select start_date_time, max(value) as value
from ((select start_date_time, value
from RevisedTable
where start_date_time between '".$start."' and '".$finish."'
) union all
(select start_date_time, value
from UnRevisedTable
where start_date_time between '".$start."' and '".$finish."'
)
) t1
group by start_date_time
您可能还会发现这比join
慢。 MySQL引擎在实现连接方面比聚合更好。
答案 1 :(得分:1)
要回答您的问题,较慢的查询使用UNION
,这将删除在第一个和第二个表之间重复的行。这将需要一种通常很昂贵的种类。您可以在查询2中将此计划视为文件排序。您可以使用UNION ALL
来消除此类排序。
您可能希望考虑将COALESCE
替换为查询1中的CASE语句,该语句将返回第一个非空值。它将使查询更容易阅读并且可以更快地运行。
SELECT
o.start_date_time,
COALESCE (o.value, r.value) AS value
FROM UnRevisedTable o LEFT JOIN RevisedTable r ON o.start_date_time = r.start_date_time
WHERE o.start_date_time >= '".$start."'
AND o.start_date_time < '".$finish."'
ORDER BY start_date_time ASC;