2013-10-27 53 views
2

我有這三個表嵌套查詢:PostgreSQL的執行緩慢

  1. 創建表的話(ID整數,字文,頻率整數);
  2. 創建表句(id整數,句子文本);
  3. 創建表索引(wordId integer,sentenceId integer,position integer);

索引是倒排索引,表示哪個詞出現在哪個句子中。 Furthermoore我有一個來自表單詞和句子的id的索引。

此查詢確定哪些句子出現一個給定的字,並返回第一個匹配:

select S.sentence from sentences S, words W, index I 
where W.word = '#erhoehungen' and W.id = I.wordId and S.id = I.sentenceId 
limit 1; 

但是,當我想要檢索其中兩個詞一起出現的一句話:

select S.sentence from sentences S, words W, index I 
where W.word = '#dreikampf' and I.wordId = W.id and S.id = I.sentenceId and 
S.id in (
    select S.id from sentences S, words W, index I 
    where W.word = 'bruederle' and W.id = I.wordId and S.id = I.sentenceId 
) 
limit 1; 

這查詢要慢得多。有什麼竅門可以加速嗎?下面的事情我做了這麼遠:

  • shared_buffer將增加至32MB
  • 增加work_mem到15MB
  • 跑分析所有表上
  • 作爲詞ID和句子ID提到創建的索引

關心。

€秩:

這裏是解釋分析查詢語句的輸出:http://pastebin.com/t2M5w4na

這三個創建語句其實我原來的創建語句。我應該將主鍵添加到表格句子和單詞中,並將它們作爲索引中的外鍵引用?但是,我應該爲索引表使用哪個主鍵? SentId和wordId在一起並不是唯一的,即使我添加表示單詞在句子中的位置的pos也不是唯一的。

更新爲:

  1. 創建表字(ID整數,字文本,頻率整數,主鍵(id));
  2. 創建表句(id整數,句子文本,主鍵(id)); (wordId integer,sentenceId integer,位置整數,外鍵(wordId)引用單詞(id),外鍵(sentenceId)引用句子(sentenceId));創建表索引
+1

編輯你的問題,並粘貼的輸出'解釋分析your_query',其中 「your_query」 代表你的麻煩SELECT語句。而且,實際的CREATE TABLE語句可以幫助很多。 –

+0

你的表'索引'(可怕的名字,BTW)至少需要一個主鍵。 「{sentenceid,position}」是明顯的選擇。在'{sentenceid,wordid}'和/或'{wordid,sentenceid}'上有一個或兩個複合索引也可能有幫助。 – wildplasser

+0

加號:對於單詞表的_natural_鍵,您需要一個UNIQUE約束或索引:「單詞」本身。不記錄:RDBMS和nlp是不匹配的。您可以查看其他存儲方法(對於Postgres:hstore或GIST索引進行全文搜索) – wildplasser

回答

1

我想這應該是更有效:

SELECT s.id, s.sentence FROM words w 
JOIN INDEX i ON w.id = i.wordId 
JOIN sentences s ON i.sentenceId = s.id 
WHERE w.word IN ('#dreikampf', 'bruederle') 
GROUP BY s.id, s.sentence 
HAVING COUNT(*) >= 2 

只需確保IN子句中的項目數量的HAVING子句中的項目數量相匹配。

小提琴here

+0

如果你想添加更多的單詞,而是改變參數,你也不需要在這個解決方案中添加更多的SQL代碼:) –

+0

非常感謝。它比我的解決方案快得多,但仍然在幾秒鐘內。也許這是因爲表格的大小:單詞(255715行),句子(5085623行)和索引(61029790行)。 – user2715478

+0

61 MM?這是一個很大的數字:)下一級的性能將在我猜測的索引上工作。但可能你應該在[dba.se]中提出這個問題。 –

0

看起來您沒有索引wordId,sentenceId。請創建它們,並且查詢將運行得更快。

CREATE INDEX idx_index_wordId ON index USING btree (wordId); 
CREATE INDEX idx_index_sentenceId ON index USING btree (sentenceId); 

使用保留字作爲index表名是不是一個好主意 - 你可能需要逃避它在某些情況下。 也許你還應該添加id列到index表,並使其成爲主鍵。

請在使用索引後使用Mosty Mostacho查詢並顯示它的輸出爲explain analyze。可能會更快。

更新:

請嘗試新的查詢:

select S.sentence from sentences S where S.id in 
(select sentenceId from index I where 
I.wordId in (select id from words where word IN ('#dreikampf', 'bruederle')) 
group by I.sentenceId 
having count(distinct I.wordId) = 2 
limit 1) 
+0

向兩個id添加了索引,並將索引表重命名爲inv_w。以下是解釋分析的輸出:pastebin.com/veVds6KP仍以秒爲單位。我只對第一個/一個匹配感興趣,所以也許我可以使用遊標?因爲此查詢檢索所有解決方案。 – user2715478

+0

請同時創建此索引: CREATE INDEX idx_words_word使用btree(字)開啓單詞;' 並在查詢結尾添加'LIMIT 1'以僅提取一行。 – alexius

+0

我也更新了我的答案 - 請嘗試新的查詢。它應該更快,更正確地工作(當兩個相同的單詞在一個句子中時處理案例)。 – alexius