我有一张桌子,里面有1600万条记录.我正在try 查询表,以确定-对于每个唯一的人-他们的记录中有多少百分比的记录上添加了标记.大约有200个独一无二的人.我的疑问是:

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

其中qa_flag是带有1或空值的tinyint字段.在person字段上设置了索引,但在qa_flag字段上没有.

此查询在任何合理时间内都不会返回.我已经让它运行了长达一个小时.更糟糕的是,我需要查询是动态的,并在网页上加载一个包含这些统计数据的表.

有人能告诉我我做错了什么吗,或者如果我本身没有做错什么,有人能建议一下加速这个查询的方法吗--显著地.

谢谢.

推荐答案

无论如何,该查询都需要执行表扫描或索引扫描,因此它必须以任何一种方式访问16M个条目.

在创建了一个包含16M行的表之后,我测试了查询的解释.

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(在索引扫描的情况下,这实际上不是行数,而是索引叶条目).

一种可能的优化是创建一个同时具有personqa_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个索引项进行索引扫描,但这是一个轻微的改进,因为在额外的字段中添加了"Using index"注释.

我try 执行该查询.考虑到它必须判断多少个索引条目,它很快就完成了:

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)

(我将Person值生成为一串随机散列.)

我正在一台搭载M1 CPU的Macbook Pro笔记本电脑上进行测试.我使用带有默认配置的MySQL 8.0.32.这不是一次超高性能的测试.

所以我猜还有其他因素阻碍了你的表现.您的硬件严重过时,或者服务器超载,或者您的客户端应用程序以某种方式阻止了您.

我建议您仔细判断数据库服务器上的负载.

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

Mysql相关问答推荐

更新MySQL表中子记录的序号

如何将左联接的小计/总计行中的所有列作废

Python - 执行原始 SQL 时获取更新查询 (Mysql) 的结果

PythonAnywhere中SSH到MySQL数据库无限期挂起,SSH正确,workbench可以完美连接

如何分解分组依据的数据?

global max_connections 和 spring.hikari.maximumPoolSize 有什么区别?

根据 Power Query 中的条件替换值

状态为已发货的订单返回产品总数量的SQL(不同的两张表)

使用另一个表中的值更新一个表中的值

从 SQL 中的左连接和内连接中减go 计数

通过 Gorm 查询模型

MariaDB 下的慢速更新、删除和插入查询

函数 mysql_real_escape_string 的 PDO 类似功能是什么?

脚本超时,如果要完成导入,请重新提交相同的文件,导入将恢复

Amazon RDS Aurora 与 RDS MySQL 与 EC2 上的 MySQL?

如何在 MySQL 中为用户设置默认架构

如何存储重复日期牢记夏令时

Sequelize Query 查找日期范围内的所有记录

将 JavaScript 到日期对象转换为 MySQL 日期格式 (YYYY-MM-DD)

MySQL 1062 - 键 'PRIMARY' 的重复条目 '0'