Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2767144
  • 博文数量: 389
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 4773
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-16 23:29
文章分类

全部博文(389)

分类: Mysql/postgreSQL

2015-04-18 17:36:01

                                Mysql  Order By列索引的影响


      Order By(以下简称OB)对排序的影响,OB列上有索引,如果不包含 where条件,类似于以下查询:

表结构

 CREATE TABLE `snapshot` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `snap_id` int(11) DEFAULT NULL,
  `name` varchar(500) DEFAULT NULL,
  `value` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `snap_id_ix` (`snap_id`),
  KEY `name_ix` (`name`(255))
) ENGINE=InnoDB


mysql> select *
    -> from snapshot
    -> order by snap_id desc;


该sql可以有两种执行计划,第一种方法是直接读取表记录,然后根据OB列去排序。
第二种方法是先扫描OB上的索引,由于索引本身就是排好序的,因此根据索引的顺序
再读出表的记录即可,省去排序的过程.

  我们可以看出第一种方法直接读取表记录就可以了.第二种方法需要先读取索引,然后根据索引去读取表记录,
io会变得很随机,因此这种方法会成本比较高,所以优化器会选择第一种执行执行划。

来看第一种执行方法的情况

mysql> explain select *
    -> from snapshot
    -> order by snap_id desc;
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | snapshot | ALL  | NULL          | NULL | NULL    | NULL | 6415 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)


mysql> show status like '%cost%';
+-----------------+-------------+
| Variable_name   | Value       |
+-----------------+-------------+
| Last_query_cost | 7721.999000 |
+-----------------+-------------+
1 row in set (0.00 sec)

执行的方式使用了全表扫描,extra中提示信息使用了排序,计划的成本是7721,这种情况下可以看出OB列上是否
有索引对排序没有什么影响.


第二种执行方法的情况,通过force index提示,强制mysql使用索引

mysql> explain select *
    -> from snapshot force index (snap_id)
    -> order by snap_id desc;
+----+-------------+----------+-------+---------------+------------+---------+------+------+-------+
| id | select_type | table    | type  | possible_keys | key        | key_len | ref  | rows | Extra |
+----+-------------+----------+-------+---------------+------------+---------+------+------+-------+
|  1 | SIMPLE      | snapshot | index | NULL          | snap_id_ix | 5       | NULL | 6415 | NULL  |
+----+-------------+----------+-------+---------------+------------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> show status like '%cost%';
+-----------------+--------------+
| Variable_name   | Value        |
+-----------------+--------------+
| Last_query_cost | 14113.999000 |
+-----------------+--------------+
1 row in set (0.00 sec)

执行使用索引,没有排序操作,但是成本变得高出将近快一倍了,所以mysql为我们选择了第一种方法.


第三种情况是limit操作带来的影响,来看两种limit操作的结果

mysql> explain
    ->  select *
    -> from snapshot
    -> order by snap_id desc
    -> limit 0,100;
+----+-------------+----------+-------+---------------+------------+---------+------+------+-------+
| id | select_type | table    | type  | possible_keys | key        | key_len | ref  | rows | Extra |
+----+-------------+----------+-------+---------------+------------+---------+------+------+-------+
|  1 | SIMPLE      | snapshot | index | NULL          | snap_id_ix | 5       | NULL |  100 | NULL  |
+----+-------------+----------+-------+---------------+------------+---------+------+------+-------+
1 row in set (0.00 sec)


mysql> explain
    -> select *
    -> from snapshot
    -> order by snap_id desc
    -> limit 100,200
    -> ;
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | snapshot | ALL  | NULL          | NULL | NULL    | NULL | 6415 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

第二个查询由于是取不同段的数据,但是之前的索引也要扫描,只是被放弃了,虽然也是取100行数据,但还是
走的全表扫描,这种情况也只能查出主键之类的,然后再去优化了.


  对于有limit之类的查询,可以看出OB列上有索引对查询计划有很大影响。现实中的查询可能更加复杂,比如where列,
连接等再需要针对具体情况再进行分析了.

 


 

阅读(4398) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~