MySQL 中的 distinct 和 group by 哪个效率更高?

一、数据库版本:Server version: 5.7.44-log

没有索引的情况下:

复制代码
mysql> select * from test1;
+----+--------------+
| id | name2        |
+----+--------------+
|  1 | test_data_1  |
|  2 | test_data_2  |
|  3 | test_data_3  |
|  4 | test_data_4  |
|  5 | test_data_5  |
|  6 | test_data_6  |
|  7 | test_data_7  |
|  8 | test_data_8  |
|  9 | test_data_9  |
| 10 | test_data_10 |
+----+--------------+
10 rows in set (0.00 sec)


mysql> explain select distinct(name2) from test1 ;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | SIMPLE      | test1 | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | Using temporary |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select name2 from test1  group by name2;;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                           |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
|  1 | SIMPLE      | test1 | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | Using temporary; Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
1 row in set, 1 warning (0.00 sec)

有索引的情况下 :

复制代码
mysql> create index idx_name2 on test1(name2);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select name2 from test1  group by name2;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test1 | NULL       | index | idx_name2     | idx_name2 | 103     | NULL |   10 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select distinct(name2) from test1 ;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test1 | NULL       | index | idx_name2     | idx_name2 | 103     | NULL |   10 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

二、数据库版本:8.0.46

没索引的情况下:

复制代码
mysql> show create table test\G
*************************** 1. row ***************************
       Table: test
Create Table: CREATE TABLE `test` (
  `id` int DEFAULT NULL,
  `a` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)


mysql> select * from test;
+------+------+
| id   | a    |
+------+------+
|    1 |    2 |
|    2 |   10 |
|    3 |    1 |
|    4 | NULL |
|    6 | NULL |
|    7 | NULL |
|    8 | NULL |
|   10 | NULL |
|   11 | NULL |
+------+------+
9 rows in set (0.00 sec)

mysql> explain  select a from test group by a;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | SIMPLE      | test  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    8 |   100.00 | Using temporary |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select distinct(a) from test;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | SIMPLE      | test  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    8 |   100.00 | Using temporary |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
1 row in set, 1 warning (0.00 sec)

总结:

  • 在语义相同,有索引的情况下:

group by和distinct都能使用索引,效率相同。因为group by和distinct近乎等价,distinct可以被看做是特殊的group by

  • 在语义相同,无索引的情况下:

distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但group by在Mysql8.0之前会进行隐式排序,导致触发filesort,sql执行效率低下。

但从Mysql8.0开始,Mysql就删除了隐式排序,所以,此时在语义相同,无索引的情况下,group by和distinct的执行效率也是近乎等价的。

相关推荐
alexhilton14 小时前
Android车载OS中的Remote Compose
android·kotlin·android jetpack
笃行35018 小时前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行35018 小时前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库
笃行35018 小时前
金仓数据库逻辑备份实战:从全库导出到 Schema 替换的完整闭环
数据库
元Y亨H18 小时前
技术笔记:MySQL 字符集排序规则与大小写敏感性问题解决方案
mysql
落魄Android在线炒饭1 天前
Android 自定义HAL开发篇之 HIDL篇——从入门到实战(上)
android
plainGeekDev1 天前
广播接收器 → Flow + Lifecycle
android·java·kotlin
plainGeekDev1 天前
EventBus → SharedFlow
android·java·kotlin
SelectDB2 天前
阶跃星辰基于 SelectDB 构建 PB 级 Agent 可观测平台
大数据·数据库·aigc