MySQL中distinct语句的基本原理及其与group by的比较

2019-01-04 16:34:51丽君

3.下面我们在看看无法单独使用索引即可完成 DISTINCT 的时候会是怎样:

sky@localhost : example 11:04:40> EXPLAIN SELECT DISTINCT user_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 set (0.00 sec)

当 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(user_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 set (0.00 sec)

最后我们再看一下这个和 GROUP BY 一起使用带有聚合函数的示例,和上面第三个示例相比,可以看到已经多了 filesort 排序操作了,正是因为我们使用了 MAX 函数的缘故。要取得分组后的 MAX 值,又无法使用索引完成操作,只能通过排序才行了。

mysql distinct和group by谁更好
1,测试前的准备

//准备一张测试表 mysql> 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 ;

  

Query OK, 0 rows affected (0.05 sec)

 

mysql> delimiter || //改变mysql命令结束符为|| //建个储存过程向表中插入10W条数据 mysql> 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||