Code前端首页关于Code前端联系我们

MySQL 中,不同或分组哪个更高效?

terry 2年前 (2023-09-26) 阅读数 61 #数据库
MySQL 中的 distinct 和 group by 哪个效率更高?首先说一下总的结论(完整的结论在文末):
  • 当语义相同且有索引时:group by 并区分即可使用具有相同效率的索引。
  • 在语义相同且没有索引的情况下:区分比 group by更有效。这是因为diff和group by都是进行分组操作,但是group by可以排序并触发文件排序,导致SQL执行效率低下。
基于这个结论,你可能会问:
  • 为什么在语义相同且有索引的情况下, group by 和 different 具有相同的效率?
  • 什么情况下会被归为
找出这两个问题的答案。接下来,我们将了解 的不同组和组的基本用法。 使用distinct
使用distinct
SELECT DISTINCT column FROM table_name WHERE condition_where;例如:例如:;-从我的学生中选择---- +
|年龄 |
+-----+
| 10 |
| 12 |
| 11 |
| NULL |
+------ +
4 rows in set (0.01s)DISTINCT 关键字用于返回唯一的不同值。它用在查询语句中的第一个字段之前,并适用于主子句中的所有列。 如果某列有 NULL 值,并且您对该列使用 DISTINCT 子句,MySQL 将保留一个 NULL 值并删除其他 NULL 值,因为 D♻※ DD 子句将所有 NULL 值视为相同的值。
distinct多列去重
distinct多列去重是基于指定的去重列信息,即只有当列中列出的所有信息都相同时,才会被视为重复信息。SELECT DISTINCT column1,coll2 FROM table_name WHERE where_conditions;
mysql> 从学生中选择不同的性别、年龄;
+--------+-------+ 性别|年龄 |
+--------+-----+
|男人| 10 |
|女 | 12 |
|男人| 11|
|男人|空 |
|女 | 11 |
+--------+------+
集合中 5 行 (0.02s)

按用途分组

用于 的基本重复数据删除用途group by相似与不同:

一列去重
语法: SELECT columns FROM table_name WHERE_conditions 执行:mysql> select Age from Students Group by Age; +------+
|年龄 |
+-----+
| 10 | 10
| 12 | 12
| 11 | 11
|空 |多列去重语法:SELECT columns FROM table_name WHERE where_conditions GROUP BY columns;执行:,,′-学生组+‽-按性别选择性别----- - - +------+
|性别 |年龄 |
+--------+-----+
|男人| 10 |
|女 | 12 | 12
|男人| 11 |
|男人|空 |
|女 | 11. group by
可以对某一列进行去重,group by的原理是先对结果进行分组排序,然后返回每组中的第一部分数据,并根据以下字段 分组。 例如:mysql> 按性别从学生组中选择性别、年龄;
+--------+-----+
|性别 |年龄 |
+--------+-----+
|男人| 10 |
|女 | 12 |
+--------+----- +
2 行一组(0.03 秒)

不同并根据原则进行分组

在大多数示例中, DISTINCT

可以看成是一种特殊的GROUP BY,它们的实现都是基于分组操作的,都可以通过自由索引扫描和紧凑索引扫描来实现(索引扫描的内容会其他文章中有详细介绍,这里就不详细介绍了)。 DISTINCTGROUP BY都可以使用索引进行扫描和搜索。比如下面两条sql(只看最后一个extra表内容),我们分析这两条sql,可以看到在extra中,这两条sql使用了紧凑索引扫描使用index for group -by 。 因此,一般情况下,对于语义相同的命令DISTINCTGROUP BY,我们可以使用相同的索引优化方法进行优化。mysql> 解释 select int1_index from group test_distinct_groupby by int1_index;
+----+-------------+------------ - ----------+----------------+--------+------------ - - ----- ----------+---------+------+--------+--------- - +-- ----- ------------------+
|编号 |选择类型 |表|隔断|类型 |可能的键 |关键| key_len |参考|线路 |过滤|额外 |
+----+------------------------+------------------------+--- --------+--------+----------------+---------+-------- - --+-----+------+----------+-------------------- - - ---+
| 1 |简单|测试_distinct_groupby |空|范围 |索引_1 |索引_1 | 5 |空| 955 | 955 100.00 |使用索引分组 |
+----+---- ---------+-------------------- - - -------------------+--- ----+----------------+----- - - --+---------+------+-- ----+---------+------------ - - --------------+
集合中的 1 行 (0.05s)mysql> 解释从 test_ 中选择不同的 int1_indexdifferent_groupby;
+----+------------------------+------------------------+- - --------+--------+--------------+------------+---- - - ---+------+------+----------+-------------------- -- ------+
|编号 |选择类型 |表|隔断|类型 |可能的键 |关键| key_len |参考|线路 |过滤|额外 |
+----+----- -------+------------------------+--- -- -----------+---- ---+--------------+------------+- -- -------+------+--- ---+------------+---------------- --- --------+
| 1 |简单|测试_distinct_groupby |空|范围 |索引_1 |索引_1 | 5 |空| 955 | 955 100.00 |使用索引分组 |
+----+------------------------+-- ------------------ - --+----------------+--------+-------- --------+-------- ---+---------+-----+------+-------- ---+------------ ----------------+
集合中1行(0.05s)但是对于对于GROUP BY,在MYSQL8.0之前,♻ GROUP Y默认会按字段排序 可以看到,下面的SQL语句虽然使用了临时表,但也已经完成了文件排序。mysql> 解释 select int6_bigger_random from test_distinct_groupby GROUP BY int6_bigger_random;
+----+---------------------------- - ----------+----------------+-----+------------- - + --- ---+---------+------+--------+------------+----- -- ---- -----------------------+
|编号 |选择类型 |表|隔断|类型 |可能的键 |关键| key_len |参考|线路 |过滤|附加功能-----------+------+--------------+-----+-------- - +------+--------+----------+------------------------ - - -----------+
| 1 |简单|测试_distinct_groupby |空 |全部 |空 |空 |空|空| 97402 | 97402 100.00 |临时使用;使用文件排序 |
+-- --+------------------------+------------------------ - +--------- ---+------+----------------+-----+----- - - ---+------ +------+----------+-------------------- - -- ------------- ---+
集合中 1 行 (0.04s)
隐式排序
对于隐式排序,我们可以参考Mysql的官方解释:https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.htmlGROUP BY默认隐式排序(即在GROUP BY 列缺少 ASC 或 DESC)。但是,不推荐使用隐式 GROUP BY 排序(即在没有 ASC 或 DESC 标签的情况下进行排序)或显式 GROUP BY 排序(即对 GROUP BY 列使用显式 ASC 或 DESC 标签)。要创建给定排序顺序,请输入 ORDER BY 子句。 综合说明: GROUP BY 默认隐式排序(即 GROUP BY 列中没有 ASC 或 DESC 指示,即使是字符也会进行排序)。但是,显式或隐式 GROUP BY 排序已被弃用。要生成给定的排序顺序,请指定 ORDER BY 子句。因此,在 Mysql8.0 之前,Group By 默认情况下会按操作字段(Group By 后面的字段)对结果进行排序。当可以使用索引时,Group By不需要额外的排序操作;但是当索引无法用于排序时,Mysql优化器必须选择使用临时表,然后按GROUP BY进行排序。 而且当结果集的大小超过系统设置的临时表的大小时,Mysql会在开始操作之前将临时表的数据复制到磁盘上,命令的执行效率会极高减少。这也是Mysql决定放弃这个操作(隐式排序)的原因。基于以上原因,Mysql在8.0版本对其进行了优化更新:https://dev.mysql.com/doc/refman/8.0/en/order-by-optimization.html此前(MySQL 5.7及以下),在某些条件下默认按GROUP BY排序。这种情况在 MySQL 8.0 中不再发生,因此不再需要在末尾指定 ORDER BY NULL 来覆盖隐式排序(就像以前那样)。但是,查询结果可能与以前版本的 MySQL 有所不同。要创建给定排序顺序,请输入 ORDER BY 子句。 综合解释: 在过去(Mysql5.7之前),Group会根据一定的条件进行隐藏操作。排序公式。在 MySQL 8.0 中,该功能被删除,因此不再需要添加 order by null 来禁用隐式排序。但是,查询结果可能与以前版本的 MySQL 有所不同。要按给定顺序获取结果,请使用 ORDER BY 语句指定要排序的字段。 因此,我们也得出结论:
  • 在语义和索引相同的情况下:
group by 和区分可以同等效率地使用索引。由于 group by 几乎等同于表达式 different,因此 different 可以被认为是特殊的 group by
  • 在语义相同且没有索引的情况下:
different 比 group by 更有效。这是因为separate和group by都会进行分组操作,但group by在Mysql8.0之前会进行隐式排序,导致文件排序和SQL执行会失效。但是从Mysql8.0开始,Mysql删除了默认的排序规则。因此,在语义相同且没有索引的情况下,执行进行分组和区分的效率几乎相当。 。 推荐group by的原因
  1. group by语义更清晰
  2. group by可以进行更复杂的数据处理与group by不同很清楚。并且由于不同的关键字会影响所有字段,因此在进行复合业务处理时,group by使用起来更加灵活,并且group by可以根据分组情况更新数据。用于复杂的处理,例如使用 has 过滤数据或使用聚合函数对数据进行操作。 版权声明:本文为CSDN博主“Sly晓”原创文章,受CC 4.0 BY-SA版权协议约束。转载时请附上原始出处的链接和本免责声明。原文链接:https://blog.csdn.net/weixin_42615847/article/details/118342524

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门