2014-05-19 37 views
2

我有相當大的表和數百萬條記錄。下面的查詢在0.2s內執行,這很好。INNER JOIN導致查詢執行時間很長

SELECT ch1.* 
FROM citizens_history ch1 
WHERE ch1.update_id_to = ( 
    SELECT MAX(ch2.update_id_to) 
    FROM citizens_history ch2 
    WHERE ch2.id = ch1.id 
) 
ORDER BY ch1.experience DESC 
LIMIT 100 

然而,當我試圖添加INNER JOIN,這樣

SELECT ch1.*, upd.* 
FROM citizens_history ch1 
INNER JOIN updates upd ON upd.id = ch1.update_id_to 
WHERE ch1.update_id_to = ( 
    SELECT MAX(ch2.update_id_to) 
    FROM citizens_history ch2 
    WHERE ch2.id = ch1.id 
) 
ORDER BY ch1.experience DESC 
LIMIT 100 

它永遠執行。在第一種情況下,我認爲MySQL是這樣:

  1. 訂單利用指數
  2. 適用WHERE
  3. 塗飾時,有100條記錄

在第二種情況下的經驗,我認爲這種情況發生:

  1. 訂單使用體驗指數
  2. 加入爲每一個記錄了數百萬行<的 - 慢
  3. 適用WHERE
  4. 完成時有100條記錄

你有任何建議如何優化呢?

編輯:EXPLAIN快速和慢速查詢:

+----+--------------------+-------+-------+---------------+------------+---------+--------------+------+-------------+ 
| id | select_type  | table | type | possible_keys | key  | key_len | ref     | rows | Extra  | 
+----+--------------------+-------+-------+---------------+------------+---------+--------------+------+-------------+ 
| 1 | PRIMARY   | ch1 | index | NULL   | experience | 3  | NULL   | 100 | Using where | 
| 2 | DEPENDENT SUBQUERY | ch2 | ref | id   | id   | 3  | db.ch1.id | 1 | Using index | 
+----+--------------------+-------+-------+---------------+------------+---------+--------------+------+-------------+ 

+----+--------------------+-------+-------+-------------------------------------+----------+---------+--------------+------+----------------------------------------------+ 
| id | select_type  | table | type | possible_keys      | key  | key_len | ref   | rows | Extra          | 
+----+--------------------+-------+-------+-------------------------------------+----------+---------+--------------+------+----------------------------------------------+ 
| 1 | PRIMARY   | upd | index | PRIMARY        | datetime | 5  | NULL   | 389 | Using index; Using temporary; Using filesort | 
| 1 | PRIMARY   | ch1 | ref | PRIMARY,update_id_to,update_id_to_2 | PRIMARY | 4  | db.upd.id | 112 | Using where         | 
| 2 | DEPENDENT SUBQUERY | ch2 | ref | id         | id  | 3  | db.ch1.id | 1 | Using index         | 
+----+--------------------+-------+-------+-------------------------------------+----------+---------+--------------+------+----------------------------------------------+ 
+1

你可以做的第一個查詢中子查詢,然後再進行加入? –

+0

我需要在我的應用程序的代碼中做很多更改。將主查詢放入子查詢中是否可行? – stil

+4

好吧,我們假設,在Explain前面添加查詢並查看查詢計劃是什麼。我預計最大的打擊將是我自己的排序。可能性的數量,但沒有執行計劃我甚至無法正確猜測 –

回答

2

重寫第一個查詢,如下所示,然後根據需要修改......

SELECT ch1.* 
    FROM citizens_history ch1 
    JOIN 
    (SELECT id 
      , MAX(update_id_to) max_update_id_to 
     FROM citizens_history 
     GROUP 
      BY id 
    ) ch2 
    ON ch2.id = ch1.id 
    AND ch2.max_update_id_to = ch1.update_id_to 
ORDER 
    BY ch1.experience DESC 
LIMIT 100 

如果你還在苦苦掙扎(performancewise),爲上述內容提供一個解釋以及所有相關表的正確DDLS。

0

執行第一階段爲連接到一個子查詢,然後加入上的更新表: -

SELECT ch1.*, upd.* 
FROM citizens_history ch1 
INNER JOIN 
(
    SELECT id, MAX(update_id_to) AS max_update_id_to 
    FROM citizens_history 
    GROUP BY id 
) ch2 ON ch1.id = ch2.id AND ch1.update_id_to = ch2.max_update_id_to 
INNER JOIN updates upd ON upd.id = ch1.update_id_to 
ORDER BY ch1.experience DESC 
LIMIT 100 
0

你可以試試:

SELECT ch1.* 
    FROM citizens_history ch1 
    LEFT JOIN citizens_history ch2 
    ON ch2.id = ch1.id 
    AND ch1.max_update_id_to > ch2.update_id_to 
    WHERE ch1.max_update_id_to is null 
    ORDER BY ch1.experience DESC 
    LIMIT 100