2016-05-22 38 views
1

我一直在研究這個小時,並且我提出的最好的代碼是來自一個我在overs found中找到的例子。我經歷了幾次派生,但以下是唯一返回正確數據的查詢,問題是僅需返回139行(超過2分鐘)就只返回30行數據。我卡住了。 (life_p是一個「喜歡」mysql使用計數的多個左連接

SELECT 
    logos.id, 
    logos.in_gallery, 
    logos.active, 
    logos.pubpriv, 
    logos.logo_name, 
    logos.logo_image, 
    coalesce(cc.Count, 0) as CommentCount, 
    coalesce(lc.Count, 0) as LikeCount 
FROM logos 

left outer join(
    select comments.logo_id, count(*) as Count from comments group by comments.logo_id 
) cc on cc.logo_id = logos.id 

left outer join(
    select life_p.logo_id, count(*) as Count from life_p group by life_p.logo_id 
) lc on lc.logo_id = logos.id 

WHERE logos.active = '1' 
    AND logos.pubpriv = '0' 
GROUP BY logos.id 
ORDER BY logos.in_gallery desc 
LIMIT 0, 30 

我不知道什麼是錯,如果我做他們單獨meaningremove的coalece和的加入之一:在運行

SELECT 
    logos.id, 
    logos.in_gallery, 
    logos.active, 
    logos.pubpriv, 
    logos.logo_name, 
    logos.logo_image, 
    count(*) as lc 
FROM logos 

left join life_p on life_p.logo_id = logos.id 

WHERE logos.active = '1' 
    AND logos.pubpriv = '0' 
GROUP BY logos.id 
ORDER BY logos.in_gallery desc 
LIMIT 0, 30 

不到半秒(2-300毫秒)....

這裏的解釋鏈接:https://logopond.com/img/explain.png

+0

通過overstack我的意思是在這裏'stackoverflow':D,感謝豪爾赫我想知道如何解決代碼顯示 –

+0

請添加解釋的結果,並請在3個受影響的表中列出索引! – Shadow

+0

Comments.logo_id,life_p.logo_id和徽標。ID都在其各自的表上編入索引。評論和徽標表格有幾列,其中一些已編入索引但與表格上的請求無關。 繼承人鏈接解釋https://logopond.com/img/explain.png –

回答

1

您可以在加入域創建一些指標:

ALTER TABLE table ADD INDEX idx__tableName__fieldNamefield

在你的情況會是這樣的:

ALTER TABLE CC使用ADD INDEX idx__cc__logo_id(logo_id);

+0

我會試試這個,並不認爲這是必要的,因爲它所引用的列是索引的,但顯然它目前沒有有效地提取。我會讓你知道,如果這是可行的 –

+0

沒有這個索引已經在適當的表中,並且只添加一個已經存在的索引。 –

2

MySQL有一個奇怪的怪癖,它允許一個group by子句不列出所有非聚合列。這不是一件好事,你應該總是在group by子句中指定所有非聚合列。

注意,計算連接表時,知道COUNT()函數忽略NULL是很有用的,因此對於可能出現NULL的LEFT JOIN,不要使用COUNT(*),而應使用加入表中,只有來自該表的行將被計​​入。從這些方面我會建議以下查詢結構。

SELECT 
     logos.id 
     , logos.in_gallery 
     , logos.active 
     , logos.pubpriv 
     , logos.logo_name 
     , logos.logo_image 
     , COALESCE(COUNT(cc.logo_id), 0) AS CommentCount 
     , COALESCE(COUNT(lc.logo_id), 0) AS LikeCount 
FROM logos 
     LEFT OUTER JOIN comments cc ON cc.logo_id = logos.id 
     LEFT OUTER JOIN life_p lc ON lc.logo_id = logos.id 
WHERE logos.active = '1' 
AND logos.pubpriv = '0' 
GROUP BY 
     logos.id 
     , logos.in_gallery 
     , logos.active 
     , logos.pubpriv 
     , logos.logo_name 
     , logos.logo_image 
ORDER BY logos.in_gallery DESC 
LIMIT 0, 30 

如果您仍然遇到性能問題,請使用執行計劃並考慮添加適合的索引。

+0

這與我在左連接方面開始時的情況更接近,但我沒有合併和所有分組bys,與此相關的問題是(需要更少的時間30秒)使like和comment列包含同樣的數字,我會試着用不同的方式運行它,但是我也沒有那麼幸運。 最終我只是試圖避免在for循環中運行查詢,因爲我通過循環獲取其他表中的徽標信息和其他所需數據。 –

+0

'select distinct'在使用該查詢時完全沒有任何效果(group by已經生成不同的行)。如果在每個組的每個連接表中恰好有相同數量的行,則計數只會相同。 –

+0

是的,我剛剛對數據庫運行了查詢,它在註釋數和類似數列中給出了完全相同的信息。我的意思是在計數註釋和計數中運行獨特內容life_p –

0

我真的不喜歡它,因爲我總是讀到子查詢是壞的,並且連接在壓力下執行得更好,但是在這種特殊情況下,子查詢似乎是在半秒內一致地提取正確數據的唯一方法。感謝大家的建議。

SELECT 
    logos.id, 
    logos.in_gallery, 
    logos.active, 
    logos.pubpriv, 
    logos.logo_name, 
    logos.logo_image, 
(Select COUNT(comments.logo_id) FROM comments 
    WHERE comments.logo_id = logos.id) AS coms, 
(Select COUNT(life_p.logo_id) FROM life_p 
    WHERE life_p.logo_id = logos.id) AS floats 

FROM logos 
WHERE logos.active = '1' AND logos.pubpriv = '0' 
ORDER BY logos.in_gallery desc 
LIMIT ". $start .",". $pageSize ." 
+0

您是否需要該查詢中的group by子句?正如你現在使用'相關的子查詢'那裏似乎沒有任何理由爲 –

+0

嗯你是對的,刪除,謝謝! –

+0

編輯刪除了該組,因爲在這種方法中沒有必要 –

0

您也可以創建一個映射表,以加快您的查詢嘗試:

CREATE TABLE mapping_comments AS 
SELECT 
    comments.logo_id, 
    count(*) AS Count 
FROM 
    comments 
GROUP BY 
    comments.logo_id 
) cc ON cc.logo_id = logos.id 

然後改變你的代碼

left outer join(

應該成爲

inner join mapping_comments as mp on mp.logo_id =cc.id 

然後每個一次新的評論被添加到th你需要更新你的映射表,或者你可以創建一個存儲過程,當你的cc表發生變化時自動執行它