MySQLDISTINCT的基本实现原理详解

更新时间:2023-07-11 18:55:19 阅读: 评论:0

MySQLDISTINCT的基本实现原理详解
前⾔
DISTINCT 实际上和 GROUP BY 操作的实现⾮常相似,只不过是在 GROUP BY 之后的每组中只取出⼀条记录⽽已。所
以,DISTINCT 的实现和 GROUP BY 的实现也基本差不多,没有太⼤的区别。同样可以通过松散索引扫描或者是紧凑索引扫描来实现,当然,在⽆法仅仅使⽤索引即能完成 DISTINCT 的时候,MySQL 只能通过临时表来完成。
但是,和 GROUP BY 有⼀点差别的是,DISTINCT 并不需要进⾏排序。也就是说,在仅仅只是 DISTINCT 操作的 Query 如果⽆法仅仅利⽤索引完成操作的时候,MySQL 会利⽤临时表来做⼀次数据的“缓存”,但是不会对临时表中的数据进⾏ filesort 操作。
当然,如果我们在进⾏ DISTINCT 的时候还使⽤了 GROUP BY 并进⾏了分组,并使⽤了类似于 MAX 之类的聚合函数操作,就⽆法避免 filesort 了。
下⾯我们就通过⼏个简单的 Query ⽰例来展⽰⼀下 DISTINCT 的实现。
1.⾸先看看通过松散索引扫描完成 DISTINCT 的操作:
艺术品的英文
sky@localhost : example 11:03:41> EXPLAIN SELECT DISTINCT group_id
-> FROM group_messageG
*************************** 1. row ***************************
id: 1
SELECT_type: SIMPLE
table: group_message
type: range
possible_keys: NULL
key: idx_gid_uid_gc
key_len: 4
ref: NULL粘土人偶
rows: 10
Extra: Using index for group-by
1 row in t (0.00 c)
我们可以很清晰的看到,执⾏计划中的 Extra 信息为“Using index for group-by”,这代表什么意思?为什么我没有进⾏GROUP BY 操作的时候,执⾏计划中会告诉我这⾥通过索引进⾏了 GROUP BY 呢?
芥末的功效与禁忌其实这就是于 DISTINCT 的实现原理相关的,在实现 DISTINCT的过程中,同样也是需要分组的,然后再从每组数据中取出⼀条返回给客户端。⽽这⾥的 Extra 信息就告诉我们,MySQL 利⽤松散索引扫描就完成了整个操作。
当然,如果 MySQL Query Optimizer 要是能够做的再⼈性化⼀点将这⾥的信息换成“Using index for distinct”那就更好更容易让⼈理解了,呵呵。
2.我们再来看看通过紧凑索引扫描的⽰例:
sky@localhost : example 11:03:53> EXPLAIN SELECT DISTINCT ur_id
-> FROM group_message
慈祥的反义词-> WHERE group_id = 2G
*************************** 1. row ***************************
id: 1
SELECT_type: SIMPLE
table: group_message
type: ref
possible_keys: idx_gid_uid_gc
key: idx_gid_uid_gc
key_len: 4
ref: const
rows: 4
Extra: Using WHERE; Using index
1 row in t (0.00 c)
情报工作这⾥的显⽰和通过紧凑索引扫描实现 GROUP BY 也完全⼀样。实际上,这个 Query 的实现过程中,MySQL 会让存储引擎扫描 group_id = 2 的所有索引键,得出所有的 ur_id,然后利⽤索引的已排序特性,每更换⼀个 ur_id 的索引键值的时候保留⼀条信息,即可在扫描完所有 gruop_id = 2 的索引键的时候完成整个 DISTINCT 操作。
3.下⾯我们在看看⽆法单独使⽤索引即可完成 DISTINCT 的时候会是怎样:
sky@localhost : example 11:04:40> EXPLAIN SELECT DISTINCT ur_id
-> FROM group_message赞美雪的优美句子
-> WHERE group_id > 1 AND group_id < 10G
*************************** 1. row ***************************
运动小健将
id: 1
SELECT_type: SIMPLE
table: group_message
type: range
possible_keys: idx_gid_uid_gc
key: idx_gid_uid_gc
key_len: 4
ref: NULL
rows: 32
Extra: Using WHERE; Using index; Using temporary
1 row in t (0.00 c)
当 MySQL ⽆法仅仅依赖索引即可完成 DISTINCT 操作的时候,就不得不使⽤临时表来进⾏相应的操
作了。但是我们可以看到,在 MySQL 利⽤临时表来完成 DISTINCT 的时候,和处理 GROUP BY 有⼀点区别,就是少了 filesort。
实际上,在 MySQL 的分组算法中,并不⼀定⾮要排序才能完成分组操作的,这⼀点在上⾯的 GROUP BY 优化⼩技巧中我已经提到过了。实际上这⾥ MySQL 正是在没有排序的情况下实现分组最后完成 DISTINCT 操作的,所以少了 filesort 这个排序操作。
4.最后再和 GROUP BY 结合试试看:
sky@localhost : example 11:05:06> EXPLAIN SELECT DISTINCT max(ur_id)
-> FROM group_message
-> WHERE group_id > 1 AND group_id < 10
-> GROUP BY group_idG
*************************** 1. row ***************************
id: 1
SELECT_type: SIMPLE
table: group_message
type: range
possible_keys: idx_gid_uid_gc
key: idx_gid_uid_gc
key_len: 4
ref: NULL
rows: 32
治疗密码Extra: Using WHERE; Using index; Using temporary; Using filesort
1 row in t (0.00 c)
最后我们再看⼀下这个和 GROUP BY ⼀起使⽤带有聚合函数的⽰例,和上⾯第三个⽰例相⽐,可以
看到已经多了 filesort 排序操作了,正是因为我们使⽤了 MAX 函数的缘故。要取得分组后的 MAX 值,⼜⽆法使⽤索引完成操作,只能通过排序才⾏了。
由于 DISTINCT的实现基本上和 GROUP BY 的实现差不多,所以这篇⽂章就不再画图展⽰实现过程了
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

本文发布于:2023-07-11 18:55:19,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1091195.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:实现   完成   操作   时候   分组
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图