MySQL查询优化器--非SPJ优化(三)--DISTINCT优化

1. DISTICT优化

MySQL支持对于DISTINCT的优化,下面通过示例具体说明。

 

示例1 MySQL支持对于DISTINCT消除的优化技术。

沿用14.1.8节示例4的用例,在有主键的e1列上执行DISTINCT,查询执行计划如下:

mysql> EXPLAIN SELECT DISTINCT e1 FROM E;

+----+-------------+-------+-------+------+-------------+

| id | select_type | table | type  | key  | Extra       |

+----+-------------+-------+-------+------+-------------+

|  1 | SIMPLE      | E     | index | e2   | Using index |

+----+-------------+-------+-------+------+-------------+

1 row in set (0.00 sec)

从查询执行计划看,在表E上执行索引扫描(type列的值为index),用以完成去重的任务。这表明MySQL利用索引这个特性对DISTINCT进行优化(注意,索引扫描的过程中MySQL没有使用主键索引而是选择了e2列上的索引)。

 

示例2 MySQL不支持对于DISTINCT推入的优化技术。

例如a2列是唯一列,又处于反半连接的语义(NOT EXISTS),完全可以把DISTINCT下推到表t_o2中先执行,然后再执行反半连接操作,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT DISTINCT b1 FROM t_o1 WHERE NOT EXISTS (SELECT 1 FROM t_o2 WHERE b1=a2);

+----+--------------------+-------+------+------+------------------------------+

| id | select_type        | table | type | key  | Extra                        |

+----+--------------------+-------+------+------+------------------------------+

|  1 | PRIMARY            | t_o1  | ALL  | NULL | Using where; Using temporary |

|  2 | DEPENDENT SUBQUERY | t_o2  | ref  | a2   | Using index                  |

+----+--------------------+-------+------+------+------------------------------+

2 rows in set, 2 warnings (0.02 sec)

被查询优化器处理后的语句为:

/* select#1 */ select distinct `tt2`.`t_o1`.`b1` AS `b1`

from `tt2`.`t_o1`

where (

    not(exists(

        /* select#2 */ select 1

        from `tt2`.`t_o2`

        where (`tt2`.`t_o1`.`b1` = `tt2`.`t_o2`.`a2`)

    ))

)

从查询执行计划看,表t_o1上使用了临时文件进行DISTINCT操作,而子查询存在没有被消除,这表明DISTINCT操作没有被推入到表t_o2中先执行,所以MySQL不支持DISTINCT推入技术。

 

示例3 MySQL支持对于DISTINCT迁移的优化技术。

例如a1a2列是唯一列,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT DISTINCT * FROM t_o1, t_o2 WHERE a1=a2;

+----+-------------+-------+------+------+------------------------------+

| id | select_type | table | type | key  | Extra                        |

+----+-------------+-------+------+------+------------------------------+

|  1 | SIMPLE      | t_o1  | ALL  | NULL | Using where; Using temporary |

|  1 | SIMPLE      | t_o2  | ref  | a2   | NULL                         |

+----+-------------+-------+------+------+------------------------------+

2 rows in set, 1 warning (0.00 sec)

从查询执行计划看,使用了临时文件完成 DISTINCT 操作,且把 DISTINCT 移入连接操作前在表 t_o1 上执行,所以 MySQL 支持 DISTINCT 迁移技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值