2016-05-22 43 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表发生变化时自动执行它