2013-05-13 65 views
1

如何改善這種嵌套查詢語句,因爲我認爲這是糟糕的表現,因爲我認爲這需要很長的時間來執行,並得到了服務器負載高如何改善這種嵌套查詢statment

SELECT user_tagtag, 
user_lastcontentid, 
(SELECT COUNT(content_id) 
FROM contents 
WHERE contents.content_id > user_lastcontentid AND 
     contents.content_id IN ( 
     SELECT contenttag_contentid 
     FROM contents_vs_tags 
     WHERE contenttag_tagtag = user_tagtag 
     ) 
) AS tag_newnews_no 
FROM users_interests_tags 
WHERE user_userid = 1 
ORDER BY user_tagsorder ASC 

users_interests_tags表結構是:

+--------------------+--------------+------+-----+---------+-------+ 
| Field    | Type   | Null | Key | Default | Extra | 
+--------------------+--------------+------+-----+---------+-------+ 
| user_userid  | bigint(20) | NO | PRI | NULL |  | 
| user_tagtag  | varchar(255) | NO | PRI | NULL |  | 
| user_lastcontentid | bigint(20) | YES | MUL | NULL |  | 
+--------------------+--------------+------+-----+---------+-------+ 

內容表的結構是:

+---------------------+----------------+------+-----+---------+----------------+ 
| Field    | Type   | Null | Key | Default | Extra   | 
+---------------------+----------------+------+-----+---------+----------------+ 
| content_id   | bigint(20)  | NO | PRI | NULL | auto_increment | 
| content_title  | varchar(255) | NO | MUL | NULL |    | 
+---------------------+----------------+------+-----+---------+----------------+ 

contents_vs_tags表結構是:

+----------------------+--------------+------+-----+---------+-------+ 
| Field    | Type   | Null | Key | Default | Extra | 
+----------------------+--------------+------+-----+---------+-------+ 
| contenttag_contentid | bigint(20) | NO | PRI | NULL |  | 
| contenttag_tagtag | varchar(255) | NO | PRI | NULL |  | 
+----------------------+--------------+------+-----+---------+-------+ 

其中contents_vs_tags.contenttag_contentid是指數和任何幫助,將不勝感激contents.content_id

的外鍵。

+0

請參見連接。它們是關係數據庫的基本概念。 – Strawberry 2013-05-13 00:20:10

回答

0

您應該爲您的標籤創建一個索引。

CREATE INDEX `idx_tag` ON users_interests_tags (user_tagtag(10)); 

CREATE INDEX `idx_tag` ON contents_vs_tags (contenttag_tagtag(10)); 

您所查詢:

SELECT t1.user_tagtag, t1.user_lastcontentid, 
    (
     SELECT COUNT(t2.content_id) 
     FROM contents t2 
     INNER JOIN contents_vs_tags t3 ON (t3.contenttag_tagtag = t1.user_tagtag) 
     WHERE t2.content_id > t1.user_lastcontentid 
      AND t3.contenttag_tagtag = t1.user_tagtag 
    ) AS tag_newnews_no 
FROM users_interests_tags t1 
WHERE t1.user_userid = 1 
ORDER BY t1.user_tagsorder ASC 

也許你仍然有您的訂單問題。一旦列沒有索引。它可以給你臨時表和文件夾。

密切關注,並使用EXPLAIN來檢查如何改善它。

3

通常相關子查詢(一個它必須爲每一行執行,從而造成巨大的性能問題),可以轉換成一個連接,和您的查詢屬於這一類:

SELECT 
    user_tagtag, 
    user_lastcontentid, 
    COUNT(distinct content_id) AS tag_newnews_no 
FROM users_interests_tags 
LEFT JOIN contents_vs_tags ON contenttag_tagtag = user_tagtag 
LEFT JOIN contents ON contents.content_id = contenttag_contentid 
WHERE user_userid = 1 
AND contents.content_id > user_lastcontentid 
GROUP BY 1, 2 
ORDER BY user_tagsorder 

通過使用LEFT JOIN,沒有匹配行的標籤仍然會返回,但是它們的計數爲零。

請注意,使用distinct可以獲得與查詢返回相同的結果。

這將執行顯着比您的查詢更好(並且明顯優於其他答案!),因爲所有訪問都直接來自tsbles,而不是通過子查詢thsn。

請確保您有對鍵列的索引:

CREATE INDEX contents_vs_tags_1 ON contents_vs_tags(contenttag_tagtag); 
CREATE INDEX contents_1 ON contents(content_id); 
+0

但這個查詢只返回1標籤不是用戶標識的所有標籤1 – 2013-05-13 00:54:35

+0

感謝您的幫助,但我測試了它的工作查詢,但它只是爲用戶返回1標籤,而不是表中的所有標籤users_interests_tags,有沒有辦法修改它返回所有他的標籤 – 2013-05-13 01:03:29

+1

哎呀!我忽略了GROUP BY。編輯答案。現在試試。 – Bohemian 2013-05-13 01:21:52