为group_concat函数优化MySQL查询

时间:2015-03-20 12:35:56

标签: mysql sql innodb myisam

SELECT SQL_NO_CACHE link.stop, stop.common_name, locality.name, stop.bearing, stop.latitude, stop.longitude
FROM service
JOIN pattern ON pattern.service = service.code
JOIN link ON link.section = pattern.section
JOIN naptan.stop ON stop.atco_code = link.stop
JOIN naptan.locality ON locality.code = stop.nptg_locality_ref
GROUP BY link.stop

上述查询大约需要800毫秒 - 1000毫秒才能运行。

如果我追加group_concat语句,则查询需要8-10秒:

SELECT SQL_NO_CACHE link.stop, link.stop, stop.common_name, locality.name, stop.bearing, stop.latitude, stop.longitude, group_concat(service.line) lines

如何使用group_concat语句更改此查询以使其在不到2秒的时间内运行?

SQL小提琴:http://sqlfiddle.com/#!9/414fe

两个查询的

EXPLAIN语句:http://i.imgur.com/qrURgzV.png

2 个答案:

答案 0 :(得分:3)

此查询需要多长时间?

SELECT p.section, GROUP_CONCAT(s.line)
FROM pattern p join
     service s
     ON p.service = s.code
GROUP BY p.section

我想你可以在子查询中执行group_concat(),因此外部查询不需要聚合。当子查询中有一个表时,这可以加快查询速度。在你的情况下,有两个。

最终结果如下:

link.section = pattern.section

SELECT SQL_NO_CACHE . . .,
       (SELECT GROUP_CONCAT(s.line)
        FROM pattern p join
             service s
             ON p.service = s.code
        WHERE p.section = link.section
       ) as lines
FROM link JOIN
     naptan.stop
     ON stop.atco_code = link.stop JOIN
     naptan.locality
     ON locality.code = stop.nptg_locality_ref;

对于此查询,您需要以下附加索引:pattern(section, service)service(code, line)

我不知道这是否有效,但值得一试。

注意:这假设您确实不需要group by用于其他列。

答案 1 :(得分:1)

一句话:你正在使用nonstandard MySQL extension to GROUP BY。它恰好适合您,因为link.stop已加入stop.atco_codepattern本身就是主键。但是你需要非常小心。

我建议你添加一些复合索引。您加入service上的section并根据ALTER TABLE pattern ADD INDEX service_section (service, section, line); 加入。所以添加这个索引。

GROUP_CONCAT()

这将使查询仅使用索引,而不必点击表本身来检索JOIN或service操作所需的信息。 (你也可能只删除(section, stop)上的索引,这个新索引使它变得多余。)

同样,您希望在link表上创建索引section,并仅在stop上删除索引。

atco_code上,您正在使用大部分列,并且您已在locality上拥有索引(PK),所以请将其设为。

最后,(code,name)WHERE anything = anything上放了一个索引。

所有这些索引猴子业务应该减少MySQL必须做的工作量来满足您的查询。

现在看一下,只要将ANALYZE TABLE xxxx添加到查询中,就可能需要向一个或多个这些索引添加一列。你绝对应该阅读multi-column indexinggrouping;良好的索引是您的数据类型的关键成功因素。

在插入大量行之后,您还应该在每个表上运行{{1}},以确保查询优化器可以查看有关表和索引内容的适当信息。