MySQL中DISTINCT与GROUP BY性能对比实测

阿橙
阿橙
发布时间:2026-10-13| 3人浏览过
原创

在实际开发中,开发者常需要在去重(DISTINCT)与分组聚合(GROUP BY)之间做选择。本文基于MySQL环境,通过构建10万行数据测试集,在无索引与有索引两种条件下对二者进行量化对比。结果表明,虽然加索引后差异微小,但在任意状态下,GROUP BY的执行效率均稳定优于DISTINCT。

测试环境与准备

为了获得具有参考意义的性能数据,我们需要在一个受控的环境中搭建测试基准。以下是具体的环境设置、表结构定义以及数据填充过程。

第1步:构建测试表

目的:创建一个包含基础ID和数值字段的测试表,用于后续的性能压测。

  1. 入口:MySQL命令行客户端或可视化工具(如Navicat、DBeaver)。
  2. 动作:执行以下建表语句。该表使用MyISAM引擎,字符集为utf8,主键为自增id。
CREATE TABLE `test_test` (
 `id` int(11) NOT NULL auto_increment,
 `num` int(11) NOT NULL default '0',
 PRIMARY KEY (`id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

第2步:生成百万级测试数据

目的:注入足够体量的数据,以消除单次查询微小的波动,确保测试结果具备统计学意义。

  1. 入口:存储过程定义界面或SQL编辑区。
  2. 动作:编写并执行存储过程。该过程会向表中插入指定数量的记录,`num`字段填充随机整数。
create procedure p_test(pa int(11)) 
begin 
declare max_num int(11) default 100000; 
declare i int default 0; 
declare rand_num int; 
select count(id) into max_num from test_test; 
while i < pa do 
if max_num < 100000 then 
select cast(rand()*100 as unsigned) into rand_num; 
insert into test_test(num) values(rand_num); 
end if; 
set i = i +1; 
end while; 
end
  1. 关键参数:调用时将 `pa` 设为 100000。
  2. 完成状态:
call p_test(100000); 

第3步:开启精细化监控

目的:常规图形界面显示的毫秒级误差难以区分极短时间的查询差异,需启用MySQL Profiler获取更精确的执行时间。

  1. 入口:SQL会话窗口。
  2. 动作:激活性能分析功能。
SET profiling=1;

无索引情况下的性能表现

在未对查询字段建立任何辅助索引的前提下,数据库需要对全表数据进行扫描和内存排序去重。

第4步:执行无索引对比查询

目的:观察底层全表扫描模式下,DISTINCT与GROUP BY的资源消耗差异。

  1. 入口:SQL编辑器。
  2. 动作:依次执行两条去重查询,并立即查看Profile报告。
SELECT DISTINCT num FROM test_test;
SELECT num FROM test_test GROUP BY num;
  1. 可观察结果:
  • DISTINCT 耗时约为 0.078ms。
  • GROUP BY 耗时约为 0.031ms。

即使在此规模下,不加索引时,两者的绝对耗时都极短,但 GROUP BY 的速度已经呈现出明显的优势。

添加索引后的性能提升

针对高频查询字段添加索引后,数据库可以直接利用索引树进行检索,大幅减少了磁盘IO和内存排序的开销。

第5步:创建测试字段索引

目的:为被查询字段 num 建立普通索引,观察索引对两类查询的加速效果。

  1. 入口:DDL操作区域。
  2. 动作:执行添加索引命令。
ALTER TABLE `test_test` ADD INDEX `num_index` (`num`);
  1. 完成状态:确认执行无误,返回索引创建成功提示。

第6步:再次执行对比查询

目的:验证索引生效后的查询耗时,并使用Profiler捕捉微小延迟。

  1. 入口:SQL编辑器及Profiler面板。
  2. 动作:重复之前的查询步骤,并在最后拉取汇总视图。
SELECT DISTINCT num FROM test_test;
SELECT num FROM test_test GROUP BY num;
SHOW PROFILES;

当耗时缩短至微秒级别时,图形界面的读数可能变为 0.000s,此时必须依赖 SHOW PROFILES 来查看详细数据。输出示例如下:

结论与分析

结合两次测试的数据,我们可以得出以下明确结论:

1. 索引带来的巨大收益

加上索引后,无论是哪种写法,查询速度都得到了数量级的提升。根据详细日志测算,加索引后的查询速度比无索引时提升了数十倍甚至上百倍,这印证了索引对于过滤操作的极端重要性。

2. GROUP BY 优于 DISTINCT

横向对比发现:
• **无索引时**:GROUP BY 比 DISTINCT 快约 2.5倍。
• **有索引时**:两者耗时均极短,但 PROFILE数据显示 GROUP BY 依然微弱领先 DISTINCT。

3. 最佳实践建议

在实际的项目开发与SQL编写中,如果你只需要对某一列(或多列)进行去重筛选,而不涉及其他聚合计算(如 SUM, COUNT),请尽量优先使用 GROUP BY 代替 DISTINCT。这不仅符合数据库底层优化的逻辑,也能保证在未来数据量级增长时保持更稳健的性能上限。

以上就是在MySQL中进行DISTINCT与GROUP BY性能对比测试的详细内容,更多关于MySQL优化实战的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。