如何加快索引列上的 GROUP BY 速度?

问题描述 投票:0回答:1

我有一个查询 带有 GROUP BY 子句,该查询在 3-4s 内执行。如果我删除 GROUP BY,执行时间会下降到 0.05 秒。 GROUP BY 已经使用索引值(-> 其中一个表的主键)。 当然,我需要 GROUP BY 子句,我无法摆脱它。

我可以做什么来加快此查询速度? (这是我的应用程序中最常用的查询之一。)

这是查询:

SELECT col1, col2, (...)
FROM table1 AS t1
JOIN table2 AS t2
   ON t2.fk_id = t1.a_id
JOIN table3 AS t3
   ON t3.fk_id = t2.id
JOIN table4 AS t4
   ON t4.fk_id = t1.b_id
JOIN table5 AS t5
   ON t5.fk_id = t4.id
LEFT JOIN table6 AS t6
   ON t6.fk_id = t1.c_id
LEFT JOIN table7 AS t7
   ON t7.fk_id = t6.id
WHERE t3.user_id = 12345
  AND t5.slug NOT IN ( 'slug_a','slug_b')
GROUP BY t1.id

编辑: 这是 EXPLAIN 命令的结果: (表名显然和我之前写的查询中的不一样......)

id 选择类型 桌子 类型 可能的键 key_len 参考 额外信息
1 简单 p (=t3) 参考 主要,partners_index_32 partners_index_32 4 常量 1 临时使用;使用文件排序
1 简单 o (=t2) 参考 主要,orders_index_1,id_client_id orders_index_1 4 apicg.p.id 228
1 简单 i (=t1) 参考 items_index_7,item_gid items_index_7 4 apicg.o.id 1 使用地点
1 简单 v (=t4) 参考 product_variants_index_17、product_variants_index_18、global_id_product_id product_variants_index_17 9 apicg.i.item_gid 1
1 简单 pr (=t5) eq_ref 主要,产品索引_16,id_名称 小学 4 apicg.v.product_id 1 使用地点
1 简单 d (=t6) 参考 to_provide,object_gid_to_validate object_gid_to_validate 8 apicg.i.global_id 6 使用地点
1 简单 inv (=t7) 参考 unique_2,invalidities_ibfk_3_idx invalidities_ibfk_3_idx 5 apicg.d.id 99503 使用地点
sql mysql
1个回答
0
投票

https://dev.mysql.com/doc/refman/8.0/en/internal-temporary-tables.html 说:

服务器在以下条件下创建临时表:

...

评估包含 ORDER BY 子句和不同的 GROUP BY 子句的语句,或者 ORDER BY 或 GROUP BY 包含连接队列中第一个表以外的表中的列。

(强调我的)

这对于您的查询意味着什么:

EXPLAIN 显示表

t3
是连接队列中的第一个表。但是你
GROUP BY t1.id
,优化器已将其放在连接队列中的第三位。

优化器可以选择对表重新排序,以便以与您在查询中指定的顺序不同的顺序访问它们。通常优化器这样做是有充分理由的,以提供更好的性能优势。

但是,如果您 GROUP BY 优化器未首先对表中的列进行排序,那么您总是会在 EXPLAIN 中看到

使用临时表

您可以尝试强制表顺序,覆盖优化器的选择。但这可能会因其他原因导致性能变差。

您可以尝试避免在磁盘上使用临时表。就像确保结果中没有

TEXT
BLOB
JSON
列(如果不需要)。或者干脆省略其他不需要的列。

您可以尝试更改磁盘临时表存储引擎。

您可以获得更快的存储设备。

您可以减少数据,使临时表更小。

您可以减少运行查询的频率,并在大多数时间依赖缓存的结果。

© www.soinside.com 2019 - 2024. All rights reserved.