2012-06-24 68 views
0

因此,我有一個包含500萬條記錄的數據庫,它存儲了問答網站的信息。該結構是...簡單的MySQL查詢需要兩個多小時

question, qid, quserid, answer, auserid; 

(QID是問題的id號)

我試圖找到所有具有特定用戶不回答問題,並通過排序它的用戶未被特定用戶回答的問題數量。這是我的查詢:

SELECT quserid, COUNT(quserid) 
FROM `qanda` 
WHERE qid NOT IN (SELECT qid FROM `qanda` WHERE auserid='myusername' GROUP BY qid) 
GROUP BY quserid 
ORDER BY COUNT(quserid) DESC 
LIMIT 0,1000; 

問題:它超過2小時,時鐘仍在滴答滴答!任何人都知道如何加快這個數據庫?我認爲數據庫中存在一個錯誤,通常最多隻需30秒就可以完成一個簡單查詢,所以這有點荒謬。任何人都知道任何調整?可能是對配置文件或其他東西的簡單更改?

..........

下面是我只是複製並粘貼數據庫中的某些數據。對不起格式。

you could have any one person in the entire wor... greendaystud ive got the person i want...its great...because sh... •glitter•rock• 191437 If you could have any one person in the entire wor... just~another~slave2tears i already got em 
          •glitter•rock• 191437 If you could have any one person in the entire wor... korn_chick2007 matt or chris... i have feelings for them 
          •glitter•rock• 189555 why are you so sexy? 
    just~another~slave2tears my b/f says i am...i dun tink so tho 
          •glitter•rock• 189555 why are you so sexy? 
    korn_chick2007 im not 
          •glitter•rock• 189555 why are you so sexy? 
    MyKool-AidsSexy  i dont think i am 
          †brokengirl† 115228 If you are supposed to expect the unexpected, 
doe... death-tone yip 
          †brokengirl† 115228 If you are supposed to expect the unexpected, 
doe... _doieverknowwhoiam_  you know whats weird? my friend sandy says that a ... 
          †brokengirl† 115228 If you are supposed to expect the unexpected, 
doe... Cute_Physco_kitty Pretty much.. 
          †brokengirl† 115228 If you are supposed to expect the unexpected, 
doe... Leslie02 WHAT! OK, now im confused! 
          †brokengirl† 114995 Why does my listerine taste like sausage this 
mor... death-tone what's listerine? 
          †brokengirl† 114995 Why does my listerine taste like sausage this 
mor... _doieverknowwhoiam_  i don't know, and maybe it's jut me bu... 
          †brokengirl† 114995 Why does my listerine taste like sausage this 
mor... darksunofdeath How old is the listerine pack? 
          †brokengirl† 114995 Why does my listerine taste like sausage this 
mor... Cute_Physco_kitty uhh... New brand of Listerine? 
    †brokengirl† 114995 Why does my listerine taste like sausage this 
mor... Leslie02 did you have sausage for breakfast?  †brokengirl† 104305 What should I name my pinky toe on my left 
foot?¿... death-tone "Pinkytoe"   

而且,預期的輸出,使用便捷的列標題...

Questioner User ID | Number of questions asked by the Questioner that were unanswered by 'myuserid' 

Greenbay Packer | 6 
DollyDoll | 63 
PsychoticPokemon | 62 
HelloKitty | 61 
GreenDayFan | 60 

...

IDontAskManyQuestion | 2<br> 
WhatsAQuestion? | 1<br> 

而這裏的EXPLAIN輸出

> mysql-> EXPLAIN 
>  -> 
>  -> SELECT quserid, COUNT(quserID) 
>  -> FROM `qanda` 
>  -> WHERE qid NOT IN (SELECT qid FROM `qanda` WHERE auserid='boxocereal' GROU P BY qid) 
>  -> GROUP BY quserid 
>  -> ORDER BY COUNT(quserid) DESC 
>  -> LIMIT 0,1000; 
> 

+----+--------------------+-------+------+---------------+------+---------+----- 
> -+---------+----------------------------------------------+ | id | select_type  | table | type | possible_keys | key | key_len | 
> ref | rows | Extra          | 
> +----+--------------------+-------+------+---------------+------+---------+----- 
> -+---------+----------------------------------------------+ | 1 | PRIMARY   | qanda | ALL | NULL   | NULL | NULL | 
> NULL | 3167995 | Using where; Using temporary; Using filesort | | 2 
> | DEPENDENT SUBQUERY | qanda | ALL | NULL   | NULL | NULL | 
> NULL | 3167995 | Using where; Using temporary; Using filesort | 
> +----+--------------------+-------+------+---------------+------+---------+----- 
> -+---------+----------------------------------------------+ 2 rows in set (0.02 sec) 
> 
> mysql-> 
+2

你有什麼指標? –

+4

MySQL是不聰明足以緩存依賴子查詢的結果,它對結果集的每一行都運行一次, – Interrobang

+0

@Interrobang,不可能是真的......真的嗎?? – McGarnagle

回答

0

基礎的在輸出中,嘗試找出候選人如果有全表掃描正在發生,您可以在那裏實施索引。

2

好的,我有一個想法將它翻譯成JOIN而不是子查詢。該技術實際上是加入其中並且來自該用戶的回答(因爲這從根本上更高效),然後從最終結果(在HAVING中)排除這些問題。這可能會進一步改善(我沒有測試過,但是IS NULL檢查可能會將改爲移入WHERE子句中)。

這是否讓你想去哪裏?

SELECT question.quserid, COUNT(question.quserid) as num_questions 
FROM qanda as question 
LEFT OUTER JOIN qanda as answers 
    ON question.qid = answers.qid AND answers.auserid = 'myusername' 
GROUP BY question.quserid 
ORDER BY num_questions DESC 
HAVING answers.auserid IS NULL; 

編輯:多一點解釋,以防萬一這是密切的,並有人可以幫助改進想法成解決方案。

基本上,查詢的主要部分將精確地選擇每個問題一次(LEFT OUTER),然後對於感興趣的用戶回答的問題,它還將選擇JOIN的列。這使我們處於候選結果集中所有問題的狀態,其中'flags'附加到我們不感興趣的那些(即非空連接的列)。然後,我們分組並拒絕具有非空連接數據的行。

+0

一個問題有很多答案,所以在一個表中可以有多個qid,這意味着qid不是這個表的主鍵。看到[這裏](http://sqlfiddle.com/#!2/3c354/2) –

+0

我想我意識到,當我設想這個解決方案。有沒有理由不會與qid有關? –

+0

事實上,這是我整個解決方案的基礎(即自我加入開啓qid)... –

0

參照@ctrahey答案我改變了查詢並得到了解決方案,因爲@ctrahey沒有給出如您所示的輸出here

你可以嘗試一下,讓我知道這是否更快?

SELECT question.quserid, COUNT(question.quserid) as num_questions 
FROM qanda as question 
LEFT OUTER JOIN qanda as answers 
    ON question.qid = answers.qid AND answers.auserid = 'user2' 
WHERE answers.auserid IS NULL 
GROUP BY question.quserid 
ORDER BY num_questions DESC; 

另見sqlfiddle。您的查詢和以上查詢給出相同的輸出。

希望這是你想要的。

+0

這是我的獨特答案嗎?語法/拼寫錯誤更改?這不是爲什麼SO允許編輯答案嗎?我甚至提到在我的回答中將HAVING移到WHERE –

0

試試這個,太:

SELECT quserid, COUNT(*) AS num 
FROM qanda 
WHERE qid NOT IN 
     (SELECT qid 
      FROM qanda 
      WHERE auserid = 'user2' 
     ) 
GROUP BY quserid 
ORDER BY num DESC 
LIMIT 0,1000 ; 

你一定會需要添加索引任何這些變體是有效的。

(qid, quserid, auserid)PRIMARY的關鍵?它是UNIQUE(我想這應該是一個兩個。

(quserid, qid)的指數也將有助於(如果你的表使用InnoDB引擎)。