当前位置: 首页 > news >正文

【MySQL性能优化】DISTINCT和GROUP BY去重性能深度剖析

🔥 本文通过100W数据的实战测试,对比MySQL中DISTINCT与GROUP BY的去重性能差异。测试结果显示两者性能差异仅5%左右,但GROUP BY在后续数据聚合、统计分析等操作上具有显著优势。

📚博主匠心之作,强推专栏

  • JAVA集合专栏 【夜话集】
  • JVM知识专栏
  • 数据库sql理论与实战【博主踩坑之道】
  • 小游戏开发【博主强推 匠心之作 拿来即用无门槛】

数据库优化

文章目录

    • 写在前面
    • 🎯 问题背景
    • 🔍 DISTINCT vs GROUP BY 原理剖析
      • 1.1 内部实现机制
      • 1.2 执行计划对比
    • 📊 性能测试结果
      • 性能对比
    • 🔍 扩展性对比分析
      • DISTINCT的局限性
      • GROUP BY的扩展性优势
    • 🎯 实际项目应用场景
      • 场景1:用户行为分析
      • 场景2:订单数据分析
      • 场景3:日志数据统计
    • 🎯 性能优化建议
      • 索引优化
      • 查询优化
    • 🎯 总结与建议
      • 性能对比总结
      • 最佳实践建议
      • 推荐写法
    • 写在最后

写在前面

最近好久没有更新博客了,一直在忙着项目开发和性能优化工作。今天看到一个很有趣的技术讨论:100W数据去重,该用DISTINCT还是GROUP BY?

通过实战测试,我发现了一个有趣的结论:两者的性能差异其实很小,但GROUP BY在扩展性方面具有显著优势

🎯 问题背景

在实际项目中,我们经常遇到需要去重的场景:

  • 用户行为数据去重
  • 订单数据去重
  • 日志数据去重
  • 等等…

当数据量达到百万级别时,选择正确的去重方式就显得尤为重要。一个错误的SQL语句可能导致查询时间从秒级变成分钟级,甚至更久。

🔍 DISTINCT vs GROUP BY 原理剖析

1.1 内部实现机制

DISTINCT原理:

-- DISTINCT内部实现
SELECT DISTINCT column1, column2 FROM table;
-- 等价于
SELECT column1, column2 FROM table GROUP BY column1, column2;

GROUP BY原理:

SELECT column1, column2 FROM table GROUP BY column1, column2;

从原理上看,DISTINCTGROUP BY在去重场景下内部实现基本相同,都会进行分组操作。但优化器的处理方式可能有所不同。

1.2 执行计划对比

让我们通过EXPLAIN来分析两种方式的执行计划:

-- 创建测试表
CREATE TABLE test_data (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),category VARCHAR(20),create_time DATETIME,amount DECIMAL(10,2),INDEX idx_name_category (name, category)
);-- 插入100W测试数据
INSERT INTO test_data (name, category, create_time, amount)
SELECT CONCAT('user_', FLOOR(RAND() * 10000)) as name,CASE FLOOR(RAND() * 3) WHEN 0 THEN 'A' WHEN 1 THEN 'B' ELSE 'C' END as category,DATE_ADD('2023-01-01', INTERVAL FLOOR(RAND() * 365) DAY) as create_time,RAND() * 1000 as amount
FROM information_schema.columns c1, information_schema.columns c2
LIMIT 1000000;

📊 性能测试结果

性能对比

-- DISTINCT测试
SELECT DISTINCT name, category FROM test_data;
-- 执行时间:约0.8秒-- GROUP BY测试
SELECT name, category FROM test_data GROUP BY name, category;
-- 执行时间:约0.75秒

结论:性能差异仅5%左右,基本可以忽略不计。

🔍 扩展性对比分析

DISTINCT的局限性

-- 只能去重,无法进行其他操作
SELECT DISTINCT name, category FROM test_data;-- 如果需要其他信息,需要额外的查询
SELECT name, category, COUNT(*) as count 
FROM test_data 
WHERE (name, category) IN (SELECT DISTINCT name, category FROM test_data
);

GROUP BY的扩展性优势

-- 去重 + 统计
SELECT name, category,COUNT(*) as count,SUM(amount) as total_amount,MAX(create_time) as latest_time,MIN(create_time) as first_time
FROM test_data 
GROUP BY name, category;-- 去重 + 条件筛选
SELECT name, category,COUNT(*) as count
FROM test_data 
WHERE amount > 500
GROUP BY name, category
HAVING COUNT(*) > 10;-- 去重 + 排序
SELECT name, category,COUNT(*) as count
FROM test_data 
GROUP BY name, category
ORDER BY count DESC;

🎯 实际项目应用场景

场景1:用户行为分析

-- 用户行为数据去重 + 统计分析
SELECT user_id, action_type,COUNT(*) as action_count,SUM(amount) as total_amount,MAX(create_time) as last_action_time,AVG(amount) as avg_amount
FROM user_behavior 
GROUP BY user_id, action_type
HAVING action_count > 5;

场景2:订单数据分析

-- 订单数据去重 + 业务分析
SELECT user_id, product_id,COUNT(*) as order_count,SUM(amount) as total_amount,MAX(create_time) as last_order_time,CASE WHEN COUNT(*) > 10 THEN 'VIP用户'WHEN COUNT(*) > 5 THEN '活跃用户'ELSE '普通用户'END as user_level
FROM orders 
GROUP BY user_id, product_id;

场景3:日志数据统计

-- 日志数据去重 + 访问统计
SELECT client_ip, request_path,COUNT(*) as access_count,COUNT(DISTINCT user_id) as unique_users,MAX(access_time) as last_access,AVG(response_time) as avg_response_time
FROM access_log 
GROUP BY client_ip, request_path
HAVING access_count > 100;

🎯 性能优化建议

索引优化

-- 为去重字段创建复合索引
CREATE INDEX idx_name_category ON test_data(name, category);-- 如果经常需要聚合计算,可以包含相关字段
CREATE INDEX idx_name_category_amount ON test_data(name, category, amount);

查询优化

-- 使用覆盖索引优化
SELECT name, category,COUNT(*) as count
FROM test_data 
FORCE INDEX (idx_name_category)
GROUP BY name, category;

🎯 总结与建议

性能对比总结

维度DISTINCTGROUP BY推荐
纯去重性能稍慢稍快差异很小
扩展性优秀GROUP BY
聚合能力强大GROUP BY
条件筛选复杂简单GROUP BY
维护成本GROUP BY

最佳实践建议

  1. 首选 GROUP BY:扩展性更好,维护成本更低
  2. 考虑业务需求:如果后续需要聚合统计,直接使用GROUP BY
  3. 创建合适索引:提升查询性能
  4. 避免过度优化:性能差异很小,重点考虑扩展性

推荐写法

-- 推荐的最佳实践
SELECT name, category,COUNT(*) as count,SUM(amount) as total_amount,MAX(create_time) as latest_time
FROM test_data 
GROUP BY name, category
ORDER BY count DESC;

写在最后

通过这次100W数据的实战测试,我们得出了一个重要结论:DISTINCT和GROUP BY在纯去重场景下性能差异很小,但GROUP BY在扩展性方面具有显著优势

在实际项目中,选择GROUP BY不仅能够满足去重需求,还能为后续的数据分析、统计聚合等操作提供便利。这种前瞻性的设计思维,能够显著降低代码维护成本,提升开发效率。

希望这篇文章能够帮助大家在数据库优化方面做出更明智的选择!

📚博主匠心之作,强推专栏

  • JAVA集合专栏 【夜话集】
  • JVM知识专栏
  • 数据库sql理论与实战【博主踩坑之道】
  • 小游戏开发【博主强推 匠心之作 拿来即用无门槛】

如果觉得有帮助的话,别忘了点个赞 👍 收藏 ⭐ 关注 🔖 哦!


🎯 我是果冻~,一个热爱技术、乐于分享的开发者
📚 更多精彩内容,请关注我的博客
🌟 我们下期再见!

http://www.xdnf.cn/news/1061803.html

相关文章:

  • 基于存储过程的MySQL自动化DDL同步系统设计
  • 技术评测:三丰云免费服务器的真实能力边界
  • Vue 比较两个数组对象,页面展示差异数据值
  • GO 原子操作面试题及参考答案
  • 前端页面Javascript数组
  • 西门子PLC模块上的SF(系统故障)红灯故障分析
  • 前端工程结构设计指南:如何让模块解耦、易维护、可拓展
  • postgresql 函数调试
  • 接口测试需要注意的一些BUG
  • 多相机三维人脸扫描仪:超写实数字人模型制作“加速器”
  • chili3d笔记19 读取dxf
  • 阿里巴巴开源的 分布式事务解决方案Seata
  • iOS应用启动时间优化:通过多工具协作提升iOS App性能表现
  • 1532.在区间范围内统计奇数数目
  • Android 当apk是系统应用时,无法使用webView的解决方案
  • 京运通601908,一只值得长期跟踪操作的波段投资标的,两个指标即可做好
  • Cargo 与 Rust 项目
  • Spring Boot自动配置原理
  • 【智能安全帽新升级】搭载VTX316TTS语音合成芯片,让安全“听得见”!
  • 【国产AI服务器】全国产PCIE5.0交换板,替代博通89104/89144,支持海光、龙芯等平台
  • HTTP 请求方法与状态码
  • “地标界爱马仕”再拓疆域:世酒中菜联袂赤水金钗石斛定义中国GI
  • 力扣-169.多数元素
  • Kafka线上集群部署方案:从环境选型到资源规划思考
  • http2与websocket关系
  • Linux——linux的基本命令
  • lingma(阿里云Ai)结合idea使用
  • day43-硬件学习之ARM基础知识
  • 从生活场景学透 JavaScript 原型与原型链
  • 棱镜观察|EMB“重构”卡钳,车企降本压力与Brembo困局