MySQL“在哪里”很慢?

时间:2015-04-30 06:45:54

标签: php mysql

我有两个表:PostsTags,用于存储用户的发布文章及其附加到文章的标签。表PostTags用于指示商品ID和标签ID的关系。结构如下:

文章:

id | title | author_id | create_time | update_time | ... #(title, author_id, create_time) is unique

标签:

id | tag_text | create_time #tag_text is unique and index

PostTags:

id | post_id | tag_id #(post_id, tag_id) is unique

我现在使用以下sql来获取带有相应标签的文章(使用group_concat)。

SELECT p.id, p.title, t.tag AS Tags FROM Posts p 
LEFT JOIN Tags t on t.id IN 
    (SELECT tag_id FROM PostTags WHERE post_id=s.id) 
GROUP BY p.id ORDER BY p.update_time DESC LIMIT 0, 10

但我发现它非常慢(对于2.5k行文章和600个标签,它需要> 3s)。如何提高性能?

EXPLAIN结果如下:

id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra

1 | PRIMARY | p | ALL | NULL | NULL | NULL | NULL | 2569 | Using temporary; Using filesort

1 | PRIMARY | t | ALL | NULL | NULL | NULL | NULL | 616   

2 | DEPENDENT SUBQUERY | PostTags | index_subquery | unique_index,tag_id,post_id | 
tag_id | 4 | func | 1 | Using where

PS,我原来的sql是(with group_concat)

SELECT p.id, p.title, group_concat(DINSTINCT t.tag) AS Tags FROM Posts p 
LEFT JOIN Tags t on t.id IN 
    (SELECT tag_id FROM PostTags WHERE post_id=s.id) 
GROUP BY p.id ORDER BY p.update_time DESC LIMIT 0, 10

但是没有group_concat的情况是一样的。

2 个答案:

答案 0 :(得分:5)

MySQL documentation describes exactly this kind of situation

  

缺点IN子查询性能的典型情况是子查询返回少量行但外部查询返回大量行以与子查询结果进行比较。

     

问题在于,对于使用IN子查询的语句,优化器会将其重写为相关子查询。 [..] 如果内部和外部查询分别返回M行和N行,则执行时间变为O(M×N),而不是O(M + N),因为它将是不相关的子查询

使用另一个连接而不是子查询将是一个更优化的解决方案:

SELECT p.id, p.title, t.tag AS Tags FROM Posts p
LEFT JOIN PostTags pt on pt.post_id = p.id
LEFT JOIN Tags t on t.id = pt.tag_id
GROUP BY p.id ORDER BY p.update_time DESC LIMIT 0, 10

答案 1 :(得分:0)

以下是group_concatgroup_concat的查询无关 做的速度。

select
p.id,
p.title,
group_concat(t.tag_text) as post_tags
from Post p 
left join PostTags pt on pt.post_id = p.id
left join Tags t on pt.tag_id = t.id
group by p.id
order by p.udate_time desc 
limit 0,10

你已经在桌面上有一些目前为止很好的索引,但是添加了另一个索引 index将提升查询

alter table Posts add index updated_time_idx(updated_time);
相关问题