2009-10-19 101 views
0

我正在設計一個測驗和quizz結果項目。所以我有兩張桌子:quizz_result和quizz。 quizz在ID上具有主鍵,quizz_result具有用於quizz標識的外鍵QUIZZ_ID。兩個左連接和一個查詢MySQL性能問題

下面的查詢旨在按日期按照排序的信息排序進行公開測驗:如果當前用戶(683735)接受了這個quizz並且有一個有效結果(> 0),並且有多少人填充了這個quizz直到此時間點。

所以我做了兩個沒有這個簡單的查詢連接:

select  
    a.*, 
    COUNT(countt.QUIZZ_ID) SUMFILL 
from 
    quizz a 
    left join quizz_result countt 
    on countt.QUIZZ_ID = a.ID 
group by 
    a.ID 

並添加索引這些列: QUIZZ:

ID, (ID, DATE), PUBLIC, (PUBLIC, DATE) 

而且在quizz_result:

ID, (QUIZZ_ID, USER_ID), QUIZZ_ID, USER_ID, (QUIZZ_ID, QUIZZ_RESULT_ID) 

但是,當我查詢時,大約需要一分鐘。我在QUIZZ_RESULTS中只有34k行,在QUIZZ表中有120行。

當我做EXPLAIN此查詢我得到這個:

SELECT TYPE: simple, possible keys: IDX_PUBLIC,DATE, rows: 34 extra: Using where; Using temporary; Using filesort 
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZZ_RES_RES_QUIZ,IDX_USERID,I..., rows: 1, extra: nothing here 
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZ_RES_RES_QUIZZ,ID_RESULT_ID, rows: 752, extra: Using index 

而且我不知道該怎麼辦,以優化此查詢什麼。我看到這個:

Using where; Using temporary; Using filesort 

但仍然我不知道如何得到這個更好,或者也許最後選擇的行數是高? 752?

如何優化此查詢?

編輯:我已經向上查詢這一隻有一個左連接,因爲它具有相同的長執行時間。編輯2:我確實刪除了所有的東西,並且它:這個簡單的選擇與一個查詢需要1s執行。如何優化它?

+0

嘗試運行OPTIMIZE TABLE QUIZZ,quizz_result; – Greg 2009-10-19 21:17:13

+0

@Greg謝謝你的提示。我做到了,但時間還是一樣的 – 2009-10-19 21:31:59

回答

0

我把它改成這樣:

select  
    a.*, 
    COUNT(a.ID) SUMFILL 
from 
    quizz a 
    left join quizz_result countt 
    on countt.QUIZZ_ID = a.ID 
group by 
    a.ID 

而且它現在是不錯的。

0

怎麼樣(USER_ID,QUIZZ_ID,QUIZZ_RESULT_ID)上的索引,因爲它們都是AND'd在一起?

+0

我認爲你是對的,應該有所幫助,但我已經將它添加到了這張表中,但不幸的是時間是相同的。所以也許這將是下一個優化。在這個查詢中仍然有很大和不好的地方 – 2009-10-19 21:26:07

+0

只剩下一個左連接仍然很慢?我沒有很多經驗,但這看起來不對。是否有很多其他需要很長時間的查詢看起來不應該?你是否將默認值中的任何數據庫引擎參數(線程,共享內存等)更改了?我猜在這之前,檢查你是否真的在quizz_result上設置了外鍵限制。 – Kev 2009-10-20 17:01:00

1

嘗試從你的連接中取出一些附加條件。 將它們移到where子句有時可以提供幫助。另外,考慮將核心連接放入它們自己的子查詢中,然後用where子句限制它。

+0

我嘗試但沒有成功,你可以更具描述性? – 2009-10-19 22:05:02

+0

由於我原來的答案你的查詢已經改變了一些,我不認爲我的答案是有效的。看看這兩張表上的索引。確保你在加入的所有列上都有索引。只要有可能,就加入每個表內的唯一值(例如主鍵和外鍵)。 – 2009-10-20 14:12:23

0

試試這個:

SELECT q.*, 
     (
     SELECT COUNT(*) 
     FROM quizz_results qr 
     WHERE qr.quizz_id = q.id 
     ) AS total_played, 
     (
     SELECT result 
     FROM qr.quizz_id = q.id 
       AND user_id = 683735 
     ) AS current_user_won 
FROM quizz q