2012-08-07 42 views
1

目前,我在data_article_key_terms表中有大約900,000個條目,以將關鍵術語與其各自的文章相關聯。目標是能夠選擇任意日期範圍,並根據該日期範圍內的文章顯示前15個關鍵字詞。按頻率和日期範圍排列關鍵字

我正在運行的問題是,我正在運行的查詢需要將近6秒,但我需要它比這更快。我意識到這是基於我正在運行的系統的相對基礎,我可以使用更多功率的機器,但我試圖在我走這條路線之前儘可能地優化它。

我使用InnoDB作爲MySQL存儲引擎來保持數據的完整性。據我瞭解,MyISAM的計數(*)更快,但使用該引擎也不是一種選擇。

我也考慮過將關鍵項計數存儲在基於固定時間範圍的表中,但這最終會導致大量數據存儲和跟蹤。

有沒有人有關於如何優化這種體驗的好建議?

我有以下表格:

該表存儲文章:

CREATE TABLE `data_article` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `connection_id` int(11) NOT NULL, 
    `folder_id` int(11) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    `uid` varchar(100) NOT NULL, 
    `date` date NOT NULL, 
    `influencer_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `data_article_5930b15a` (`connection_id`), 
    KEY `data_article_4e5f642` (`folder_id`), 
    KEY `data_article_fbfc09f1` (`user_id`), 
    KEY `data_article_43ae76a1` (`influencer_id`), 
    KEY `data_article_date` (`date`), 
    CONSTRAINT `connection_id_refs_id_b2ae9152` FOREIGN KEY (`connection_id`) REFERENCES `account_connection` (`id`), 
    CONSTRAINT `folder_id_refs_id_e343586a` FOREIGN KEY (`folder_id`) REFERENCES `account_folder` (`id`), 
    CONSTRAINT `influencer_id_refs_id_45cd3615` FOREIGN KEY (`influencer_id`) REFERENCES `data_influencer` (`id`), 
    CONSTRAINT `user_id_refs_id_aca13cc9` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`) 
) 

此表存儲關鍵術語:

CREATE TABLE `data_keyterm` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `term` varchar(100) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `data_keyterm_term` (`term`) 
) 

此表存儲文章和關鍵術語之間的關係:

CREATE TABLE `data_article_key_terms` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `article_id` int(11) NOT NULL, 
    `keyterm_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `article_id` (`article_id`,`keyterm_id`), 
    KEY `data_article_key_terms_30525a19` (`article_id`), 
    KEY `data_article_key_terms_1d848ca4` (`keyterm_id`), 
    CONSTRAINT `article_id_refs_id_d87be8f5` FOREIGN KEY (`article_id`) REFERENCES `data_article` (`id`), 
    CONSTRAINT `keyterm_id_refs_id_50d233f8` FOREIGN KEY (`keyterm_id`) REFERENCES `data_keyterm` (`id`) 
) 

與該物品相關的該表存儲有影響力:

CREATE TABLE `data_influencer` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(100) NOT NULL, 
    `title` varchar(100) NOT NULL, 
    `email` varchar(100) NOT NULL, 
    `active` tinyint(1) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `data_influencer_fbfc09f1` (`user_id`), 
    KEY `data_influencer_name` (`name`), 
    CONSTRAINT `user_id_refs_id_b1bb5d4f` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`) 
) 

這是SQL語句我使用基於時間範圍內,他們組拉的關鍵字,並責令其按頻率:

SELECT dk.id, dk.term as term, COUNT(dk.id) as count 
FROM data_keyterm dk 
INNER JOIN data_article_key_terms dakt ON dakt.keyterm_id = dk.id 
INNER JOIN data_article da ON da.id = dakt.article_id 
INNER JOIN data_influencer di ON di.id = da.influencer_id 
WHERE da.user_id = 1 
AND da.date between '2010-08-07' AND '2012-08-07' 
AND di.active = True 
GROUP BY dk.id 
ORDER BY count DESC 
LIMIT 15; 
+0

您最後的SQL語句看起來不是有效的GROUP BY語句。你可以仔細檢查? – Olaf 2012-08-07 15:01:49

+0

是的,這是正確的,這個聲明運行沒有問題。 – bmorrise 2012-08-07 15:04:01

+0

@Olaf:這不是有效的SQL GROUP BY子句,但[它在MySQL中有效](http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html)。 – 2012-08-07 15:40:31

回答

0

運行帶有900,000記錄和3內連接的表的內連接將需要一些時間來執行。我認爲你應該嘗試一些外部搜索引擎如太陽能在快速時間獲得結果

+0

Can Solr能處理這樣的搜索嗎? – bmorrise 2012-08-07 15:04:42

+0

是的,它處理。你有你創建索引正確獲得這樣的結果 – Ashish 2012-08-07 15:10:36

+0

謝謝你的Solr提示。我最終使用它,它運作得非常好。 – bmorrise 2014-08-08 13:39:43

0

我想知道,在這種情況下,索引可能沒有幫助你。查詢的選擇性是什麼?也就是說,正在使用多少文章/組合鍵?

爲了優化性能,我認爲查詢計劃應該按用戶ID和日期選擇文章,然後進行連接。然後將這個縮減的子集用於其他連接。相反,我懷疑它始終使用索引。

我的第一個建議是使用單個索引替換文章列表上的userid/date兩個索引。 WHERE子句可以使用這個單個索引來滿足條件。這可能會簡化和改進查詢計劃。

要測試的另一件事是反規範文章/關鍵表一點。假設鍵和文章是同時創建的,請將用戶標識和日期添加到此表中。然後,只需將您的查詢改爲對此表的限制即可。然後,您可以在用戶標識和日期上有複合索引。但是,我不建議在這些領域有單獨的索引。