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的执行效率也是近乎等价的。

相关推荐
程思扬1 小时前
Android 悬浮窗状态错乱终极解决方案:告别 onResume
android·网络
duke8692672141 小时前
C# 文件上传的服务器端加密 C#如何在存储到S3或Azure Blob时启用加密
jvm·数据库·python
yoyo_zzm1 小时前
ThinkPHP1.X核心特性解析
数据库·spring boot·nginx
云边有个稻草人1 小时前
金仓数据库标量子查询消除:解决复杂SQL性能瓶颈
数据库·sql·性能调优·金仓数据库·kes·标量子查询·数据库内核
逸Y 仙X1 小时前
文章二十九:ElasticSearch分桶聚合
android·大数据·elasticsearch·搜索引擎·全文检索
小杍随笔1 小时前
【LiteAdmin(sql-admin)项目前后端架构深度分析】
数据库·sql·架构·rust
C137的本贾尼2 小时前
CRUD 入门:数据的增、查、改、删
mysql
2301_808414382 小时前
MySQL中的复合查询和索引
数据库·mysql
我也不曾来过12 小时前
MYSQL的基本查询
数据库·mysql