2009-05-04 64 views
3

這裏是我的查詢:是否有比「大數表」更快的東西?

select word_id, count(sentence_id) 
from sentence_word 
group by word_id 
having count(sentence_id) > 100; 

表sentenceword包含3個字段,的wordID,sentenceid以及一個主鍵ID。 它有350k +行。 這個查詢需要高達85秒,我想知道(希望,祈禱?)有一個更快的方式來找到所有的wordids有超過100個罪犯。

我試過拿出select count部分,只是做'有數(1)',但都沒有加速。

我很感激任何幫助,你可以借。謝謝!

+1

哪些DBMS您使用的? – 2009-05-04 05:56:04

+0

這是與MySQL(並使用HeidiSQL作爲客戶端訪問它) – Jeff 2009-05-04 21:30:53

+0

另一個惱人的澄清...(對不起):數據不斷變化。約10k插入行/天和〜5k刪除行。所以我認爲這使得存儲或緩存結果不可能 – Jeff 2009-05-04 21:47:38

回答

3

having count(sentence_id)> 100;

這有一個問題......這個表有兩個重複的單詞/句子對,或者它沒有。

如果它確實有重複的單詞/句子對,你應該使用這個代碼來得到正確的答案:

HAVING COUNT(DISTINCT Sentence_ID) > 100 

如果表中沒有重複的單詞/句子對...那麼你不應該計算sentence_ids,你應該只計數行。

HAVING COUNT(*) > 100 

在這種情況下,你可以創建一個索引上word_id只有,以獲得最佳性能。

1

如果經常執行該查詢,並且表格很少更新,則可以使用單詞ID和相應的句子計數來保留一個輔助表格 - 難以想到除此之外的任何進一步優化!

+4

你的意思是,像一個索引? :-) – bignose 2009-05-04 05:40:05

6

如果還沒有,請在sentence_id,word_id上創建一個複合索引。

+0

我相信這個索引的列的正確順序是(word_id,sentence_id)。 – 2009-05-04 07:19:47

1

你的查詢很好,但它需要一些幫助(索引)來獲得更快的結果。

我沒有手頭資源(或訪問SQL),但我會嘗試從內存中爲您提供幫助。

從概念上講,回答該查詢的唯一方法是計算共享相同word_id的所有記錄。這意味着查詢引擎需要快速查找這些記錄。沒有word_id上的索引,數據庫唯一能做的就是一次遍歷表中的一條記錄,並繼續運行找到的每個單獨的word_id的總計。這通常需要臨時表,並且在掃描整個表之前不會派發任何結果。不好。

隨着word_id上的索引,它仍然需要通過表,所以你會認爲它沒有什麼幫助。但是,SQL引擎現在可以計算每個word_id的計數,而不必等到表的結尾:它可以分派行和word_id的值的計數(如果它通過您的where子句),或者放棄該行(如果它不);這將導致服務器上的內存負載較低,可能部分響應,並且臨時表不再需要。第二個方面是並行性;通過word_id上的索引,SQL可以將作業分成塊,並使用不同的處理器核並行運行查詢(取決於硬件功能和現有工作負載)。

這可能足以幫助您查詢;但你必須嘗試看看:

CREATE INDEX someindexname ON sentence_word (word_id) 

(T-SQL語法;其中SQL產品使用的是沒有指定)。如果這還不夠

(或不利於在所有),還有其他兩種解決方案。

首先,SQL允許您使用索引視圖和其他機制預先計算COUNT(*)。我手邊沒有細節(我不經常這樣做)。如果您的數據不會經常更改,那麼這會給您更快的結果,但複雜性和存儲空間有限。

此外,您可能需要考慮將查詢的結果存儲在單獨的表中。只有數據不會改變,或者按照精確的時間表(例如,在早上2點的數據刷新期間),或者如果數據變化很小,並且幾個小時內您可以忍受非完美的結果(您將不得不安排定期數據刷新);這就是窮人數據倉庫的道德等價物。

確定什麼適合您的最好方法是運行查詢並查看帶有和不帶有一些候選索引的查詢計劃。

0

還有的竟然是實現這一大型數據集的更快的方法:

SELECT totals.word_id, totals.num 
    FROM (SELECT word_id, COUNT(*) AS num FROM sentence_word GROUP BY word_id) AS totals 
WHERE num > 1000; 
相關問題