视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
MySQL中索引优化distinct语句及distinct的多字段操作_MySQL
2020-11-09 20:15:01 责编:小采
文档


MySQL通常使用GROUPBY(本质上是排序动作)完成DISTINCT操作,如果DISTINCT操作和ORDERBY操作组合使用,通常会用到临时表.这样会影响性能. 在一些情况下,MySQL可以使用索引优化DISTINCT操作,但需要活学活用.本文涉及一个不能利用索引完成DISTINCT操作的实例.

实例1 使用索引优化DISTINCT操作

create table m11 (a int, b int, c int, d int, primary key(a)) engine=INNODB;

insert into m11 values (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8);

explain select distinct(a) from m11;

mysql> explain select distinct(a) from m11;

代码如下:

+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+| 1 | SIMPLE | m11 | NULL | index | PRIMARY | PRIMARY | 4 | NULL | 1 | 100.00 | Using index |+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+


说明:
1 'a'列上存在主键索引,MySQL可以利用索引(key列值表明使用了主键索引)完成了DISTINCT操作.

2 这是使用索引优化DISTINCT操作的典型实例.

实例2 使用索引不能优化DISTINCT操作

create table m31 (a int, b int, c int, d int, primary key(a)) engine=MEMORY;

insert into m31 values (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8);

explain select distinct(a) from m31;

 mysql> explain select distinct(a) from m31;

代码如下:


+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | m31 | NULL | ALL | NULL | NULL | NULL | NULL | 8 | 100.00 | NULL |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+



说明:
1 从查询执行计划看,索引没有被使用.

2 对比实例1的建表语句,只是存储引擎不同.

3 为什么主键索引没有起作用? 难道MEMORY存储引擎上的索引不可使用?

实例3 使用索引可以优化DISTINCT操作的Memory表

create table m33 (a int, b int, c int, d int, INDEX USING BTREE (a)) engine=MEMORY;

insert into m33 values (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8);

explain select distinct(a) from m33;

 mysql> explain select distinct(a) from m33;

+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | m33 | NULL | index | NULL | a | 5 | NULL | 8 | 100.00 | NULL |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------+
说明:
1 'a'列上存在主键索引,MySQL可以利用索引(key列值表明使用了主键索引)完成了DISTINCT操作.

2 对比实例2,可以发现,二者都使用了Memory引擎. 但实例3指名使用Btree类型的索引.

3 实例2没有指定使用什么类型的索引,MySQL将采用默认值. MySQL手册上说:

As indicated by the engine name, MEMORY tables are stored in memory. They use hash indexes by default, which makes them very fast for single-value lookups, and very useful for creating temporary tables.

结论:

1 看索引对查询的影响,要注意索引的类型.

2 HASH索引适合等值查找,但不适合需要有序的场景,而Btree却适合有序的场景.

3 看查询执行计划,发现索引没有被使用,需要进一步考察索引的类型.

DISTINCT不能选择多个字段的解决方法
在实际应用中,我们经常要选择数据库某表中重复数据,通常我们是使用DISTINCT函数。

但DISTINCT只能对一个字段有效,比如:

sql="select DISTINCT title from Table where id>0"

当我们需要列出数据中的另一列,比如:

sql="select DISTINCT title,posttime from Table where id>0" 

得出的结果就不是我们想要的了,所以我们需要用另外的方法来解决这个问题。

下面的是我写的SQL语句,我不知道是不是很好,但愿有更好的人拿出来分享一下:

写法一:

sql = "Select DISTINCT(title),posttime From Table1 Where id>0"

写法二:

sql = "Select title,posttime From Table1 Where id>0 group by title,posttime"

写法三:

sql="select title,posttime from Table where id in (select min(id) from Table group by title)"

下载本文
显示全文
专题