2012-05-10 67 views
2

我正在使用MySQL在wiki上構建正向索引。我正在與查詢的性能問題,我希望一些幫助優化無論是我的架構或我的查詢在MySQL中優化正向索引

數據庫是1GB左右,它有三個表

  • fi_page是800K的wiki頁面表
  • fi_keyword是70K關鍵字

    CREATE TABLE `fi_keyword` ( 
        `id` int(11) NOT NULL AUTO_INCREMENT, 
        `keyword` varchar(100) NOT NULL, 
        PRIMARY KEY (`id`), 
        UNIQUE KEY `keyword` (`keyword`) 
    ); 
    
  • fi_titlekeywordlink是一臺6萬個條目鏈接的關鍵字維基頁面

    CREATE TABLE `fi_titlekeywordlink` (
        `id` int(11) NOT NULL AUTO_INCREMENT, 
        `keyword_id` int(11) NOT NULL, 
        `page_id` int(11) NOT NULL, 
        PRIMARY KEY (`id`), 
        KEY `fi_titlekeywordlink_a6434082` (`keyword_id`), 
        KEY `fi_titlekeywordlink_c2d3d2bb` (`page_id`), 
        CONSTRAINT `keyword_id_refs_id_67197756` FOREIGN KEY (`keyword_id`) REFERENCES `fi_keyword` (`id`), 
        CONSTRAINT `paper_id_refs_id_705ddf03` FOREIGN KEY (`page_id`) REFERENCES `fi_page` (`id`) 
    ); 
    

我翻譯了關於「條款的稱譽」的搜索到一個SQL查詢如

select p.* 
     from 
     fi_keyword as k0, fi_titlekeywordlink as l0, 
     fi_keyword as k1, fi_titlekeywordlink as l1, 
     fi_keyword as k2, fi_titlekeywordlink as l2, 
     fi_keyword as k3, fi_titlekeywordlink as l3, 
     fi_page as p 
     where 
     k0.keyword = e and k0.id = l0.keyword_id and p.id = l0.paper_id 
     and k1.keyword = 'search' and k1.id = l1.keyword_id and p.id = l1.paper_id 
     and k2.keyword = 'terms' and k2.id = l2.keyword_id and p.id = l2.paper_id 
     and k3.keyword = 'galore' and k3.id = l3.keyword_id and p.id = l3.paper_id 
     limit 1,10 

然而,這正在圍繞半秒到我的MBP運行。對於如何通過更改模式或查詢來加速這種操作,你有什麼建議嗎?在這種情況下,我不能使用單獨的搜索服務器,正向索引必須在MySQL上運行。謝謝。

+0

什麼表引擎? InnoDB的? –

+0

@MarcusAdams是的,但我很樂意改變 – Duncan

回答

2

在插入性能爲代價,你可以刪除這兩個表替代id主鍵列,並就爲fi_titlekeywordlink主鍵索引的keyword列fi_keyword和(keyword_idpage_id)你的主鍵索引。

如果您使用的是InnoDB,主鍵是聚簇索引,因此速度更快。

即使您沒有進行此更改,fi_titlekeywordlink上的複合(多列)索引(keyword_id,page_id)也會提高性能,因爲您將擁有覆蓋索引(MySQL不必訪問表數據)在fi_titlekeywordlink上。這假設你的MySQL服務器有足夠的內存來適應內存中的所有索引,並且你已經配置了MySQL服務器來允許它使用足夠的內存來完成它(配置變量在MyISAMInnoDB之間不同)。

有時,隱式JOIN會變得太複雜,MySQL無法正確優化。您還應該考慮使用JOINON以顯式ANSI標準連接重寫查詢。

爲簡潔起見,您可能只是寫了SELECT p.*,但請務必只選擇需要的列,以便不返回不需要的數據。只返回你需要的列減少了工作量。

此外,LIMIT子句中的第一行爲0,所以LIMIT 1, 10跳過第一行。使用LIMIT 0, 10獲得前10行。

+0

感謝您的快速響應,我將通過這些建議。 – Duncan

+0

我已經添加了一個複合索引並交換到ansi連接語法,這已經幫助了很多。要弄清楚如何改變主鍵需要更長的時間,但我也會這樣做。謝謝你的幫助。 – Duncan