2012-09-28 86 views
2

我有這個疑問SQL數據庫索引設計內加入關鍵字搜索

SELECT a.* 
FROM entries a 
INNER JOIN entries_keywords b ON a.id = b.entry_id 
INNER JOIN keywords c ON b.keyword_id = c.id 
WHERE c.key IN ('wake', 'up') 
GROUP BY a.id 
HAVING COUNT(*) = 2 

,但它的速度慢。我如何優化設計索引以加快速度?

編輯 這是當前模式

CREATE TABLE `entries` (`id` integer PRIMARY KEY AUTOINCREMENT, `sha` text); 
CREATE TABLE `entries_keywords` (`id` integer PRIMARY KEY AUTOINCREMENT, `entry_id` integer REFERENCES `entries`, `keyword_id` integer REFERENCES `keywords`); 
CREATE TABLE `keywords` (`id` integer PRIMARY KEY AUTOINCREMENT, `key` string); 
CREATE INDEX `entries_keywords_entry_id_index` ON `entries_keywords` (`entry_id`); 
CREATE INDEX `entries_keywords_entry_id_keyword_id_index` ON `entries_keywords` (`entry_id`, `keyword_id`); 
CREATE INDEX `entries_keywords_keyword_id_index` ON `entries_keywords` (`keyword_id`); 
CREATE INDEX `keywords_key_index` ON `keywords` (`key`); 

我使用SQLITE3,查詢不會失敗,但速度很慢。

現在我這樣的查詢(子查詢爲每個關鍵字):

select * 
from (
    select * 
    from (entries) e 
    inner join entries_keywords ek on e.id = ek.entry_id 
    inner join keywords k on ek.keyword_id = k.id 
    where k.key = 'wake') e 
inner join entries_keywords ek on e.id = ek.entry_id 
inner join keywords k on ek.keyword_id = k.id 
where k.key = 'up'; 

這是方式更快,但感覺不對,因爲它會變得醜陋,如果我有很多的關鍵字。

+0

你現在有什麼指標? – Taryn

+0

引用列上的索引將有所幫助。緩慢的部分可能是最後一點..計數*對於性能不是很好。我假設這是mysql,但如果它是另一個數據庫,你可以使用keywords.key的部分索引作爲優化。 –

+0

'keywords.key'編入索引嗎? –

回答

1

該查詢所需的關鍵指標

  • 關鍵字(關鍵字)
  • entries_keywords(keyword_id,entry_id)
  • 條目(ID)

您必須使用MySQL,因爲否則SELECT a。*會失敗。
編輯對本聲明的第二個評論之後,讓我指出爲什麼select a.*會在這裏失敗 - 這是因爲GROUP BY的。

解釋一下,因爲條件(WHERE)在c.key上,所以需要對它進行索引。
然後,這會對b.keyword_id加入JOIN。我們創建一個包含b.entry_id的索引,以便它永遠不必查詢表格 - 索引本身可以覆蓋所需的列。
最後,a.id = b.entry_id加入到條目表中,因此我們索引該表的id。

這很可能entries(id)已經是主鍵,但你可能有entries_keywords索引周圍的其他的方式 - 它不會工作,以滿足此連接。

+0

SELECT a。*在我所知道的任何RDBMS中都受支持...... – amphibient

+0

「失敗」是一個相對術語,不幸的是。 MySQL允許您省略SQL標準和其他大部分DBMS要求的GROUP BY列表中的所有列 - 所有非聚合的列應正常列在GROUP BY子句中。 MySQL對此更爲寬鬆,並選擇要顯示的值以適應自身。在分組列構成表的主鍵(或另一候選鍵)的超集的情況下,它可以得到你想要的答案;但是如果您正在分組的列不構成表的候選鍵的超集,則不確定性。 –

+0

@JonathanLeffler:確切地說,即使SQL-2003 +標準不在「GROUP BY」子句中,也允許在「SELECT」列表中使用列。只要他們在功能上依賴於他們。 (不是MySQL做任何檢查,他們已經以一種相當馬虎的方式實現了這一點 - 允許在查詢中使用非標準的使用和半隨機的結果。) –