Group By 查询运行速度太慢无法正常运行

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

我有一张包含 ~16M 记录的表。我正在尝试查询表以确定 - 对于每个独特的人 - 他们的记录中有多少百分比被标记在他们身上。大约有200个独特的人。我的查询是这样的:

select person, concat((sum(qa_flag)/count(*))*100, '%') 
from myTable 
group by person;

其中

qa_flag
是一个 1 或 null 的 tinyint 字段。
person
字段上有一个索引集,但
qa_flag
字段上没有。

此查询不会在任何合理时间内返回。我让它运行了一个小时。更糟糕的是,我需要动态查询并使用这些统计信息在网页上加载表格。

有人可以告诉我我做错了什么,或者如果我本身没有做错任何事,有人可以建议加快查询速度的方法 - 显着。

谢谢。

mysql sql query-optimization
1个回答
0
投票

不管怎样,这个查询都需要进行表扫描或索引扫描,因此它必须以任何一种方式访问 16M 条目。

我在创建一个包含 1600 万行的表后为您的查询测试了 EXPLAIN。

mysql> explain select person, concat((sum(qa_flag)/count(*))*100, '%') 
    -> from myTable 
    -> group by person;
+----+-------------+---------+------------+-------+---------------+--------+---------+------+----------+----------+-------+
| id | select_type | table   | partitions | type  | possible_keys | key    | key_len | ref  | rows     | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+--------+---------+------+----------+----------+-------+
|  1 | SIMPLE      | myTable | NULL       | index | person        | person | 129     | NULL | 16329623 |   100.00 | NULL  |
+----+-------------+---------+------------+-------+---------------+--------+---------+------+----------+----------+-------+

这显示了一个索引扫描 (

type: index
),估计“行”数约为 16M(在索引扫描的情况下,这实际上不是行数,而是索引叶条目)。

一个可能的优化是创建一个同时具有

person
qa_flag
的新索引,作为覆盖索引。这样它就可以产生只读取索引的结果,而不触及表行。

mysql> alter table mytable add key (person, qa_flag);
Query OK, 0 rows affected (22.11 sec)

mysql> explain select person, concat((sum(qa_flag)/count(*))*100, '%') 
    -> from myTable 
    -> group by person;
+----+-------------+---------+------------+-------+-----------------+----------+---------+------+----------+----------+-------------+
| id | select_type | table   | partitions | type  | possible_keys   | key      | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+---------+------------+-------+-----------------+----------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | myTable | NULL       | index | person,person_2 | person_2 | 131     | NULL | 16329623 |   100.00 | Using index |
+----+-------------+---------+------------+-------+-----------------+----------+---------+------+----------+----------+-------------+

这仍然对 ~16M 索引条目进行索引扫描,但由于额外字段中的“使用索引”注释,它略有改进。

我尝试执行查询。考虑到它必须检查多少索引条目,它很快就完成了:

mysql> select person, concat((sum(qa_flag)/count(*))*100, '%')  from myTable  group by person limit 2;
+----------------------------------+------------------------------------------+
| person                           | concat((sum(qa_flag)/count(*))*100, '%') |
+----------------------------------+------------------------------------------+
| 0000023f507999464aa2b78875b7e5d6 | 0.0000%                                  |
...
| fffffe98d0963d27015c198262d97221 | 0.0000%                                  |
+----------------------------------+------------------------------------------+
16777216 rows in set (8.64 sec)

(我将人的值生成为一堆随机哈希值。)

我正在使用 M1 CPU 的 Macbook Pro 笔记本电脑上进行测试。我使用默认配置的 MySQL 8.0.32。这不是超高性能测试

所以我想还有其他事情阻碍了你的表现。要么你的硬件严重过时,要么服务器超载,要么你的客户端应用程序以某种方式阻止了你。

我建议您仔细检查数据库服务器上的负载。

还使用 query profiling 来获取查询花费时间的更多详细信息。我知道您说过查询需要一个多小时,但是您应该能够通过在行数较少的表上进行测试来获得完成的查询。

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