2014-05-07 57 views
2

我有兩個表。在該表中UnRevisedTable而來的原始數據,並在表RevisedTable有哪些,當他發現在UnRevisedTable比他不喜歡的值人類插入修正值的唯一入口。從兩個表查詢:消耗時間

UnRevisedTable有每分鐘一個條目和RevisedTable沒有在UnRevisedTable每一個不必要的侵入一個條目。

這兩個查詢的目的是相同的:當修改數據時,請告訴我修改數據和無修改數據的聯合,替換未修改數據。

我開始編寫query2,但速度太慢。然後我寫了query1,而且query1要快得多。

我的問題是爲什麼query1比query2快?謝謝。

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 sugested這裏的解釋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 |         | 
+----+--------------+------------+-------+---------------+---------+---------+------+------+---------------------------------+ 
+2

使用'先解釋第一個查詢'然後'解釋第二個查詢'並在問題中分享結果。 –

回答

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引擎在實現連接方面做得比聚合更好。

+0

你好。首先感謝您的答案。我在繪製數據,所以我很快發現兩個qiereis不完全一樣,你的解釋肯定幫助我更好地理解它們。 這兩個表中的數據量很大(10年一次,每1分鐘一次)。正如我所說,即時繪製這些數據並繪製這麼多的數據是不可能的。我使用這兩個查詢作爲查詢的子查詢,按時間間隔對我的數據進行分組。有這樣一個複雜的查詢和這麼多的數據使所有的過程變得緩慢。我要去討論這些冒險和缺點。 –

1

若要回答您的問題,較慢的查詢使用UNION,它刪除第一個和第二個表之間重複的行。這將需要經常昂貴的種類。您可以在查詢2的計劃中看到這是一個文件。您可以改用UNION ALL來消除此類問題。

您可能會考慮將查詢1中的CASE語句替換爲COALESCE,它將返回第一個非空值。這將使更容易閱讀的查詢,並可能運行得更快。

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; 
+0

Thx爲答案。 林進行嘗試聯盟所有。 COALESCE不會有用,因爲某些時候數據的復位會將值設置爲空。 –