loose index scan 优化distinct

  • 时间:
  • 浏览:2

+———————-+

+———-+

+—-+————-+——————————+——-+—————+————-| id | select_type | table                        | type  | possible_keys | key                             | key_len | ref  | rows    | Extra                    |

+———————-+

+—-+————-+——————————+——-+—————+————-

| id | select_type | table                        | type  | possible_keys | key                        | key_len | ref  | rows     | Extra       |

|   4006934 |

.我 歌词 知道索引的值是按照索引字段升序的,比如.我 歌词 对(nick,other_column)有有一有1个字段做了索引,没办法 在索引中的则是按照nick,other_column的升序排列:

1 row in set (52.78 sec)

+———————-+

最重要的是在子查询中:select distinct(nick) 实现了上图中的伪loose index scan,优化器在这一时候的执行计划为Using index for group-by ,

须要注意的是mysql把distinct优化为group by,它首先利用索引来分组,有时候 扫描索引,对须要的nick只扫描一次;

原始写法:

执行一次sql需为宜52.78s,原应非常的慢了

root@db 09:00:12>select count(distinct nick) from user_access;

有有一有1个sql的执行计划分别为:

没办法 上方过程会扫描可是重复的nick,原应.我 歌词 都还可否跳过上方重复的nick,则性能会优化非常多(在oracle中,这一扫描技术为loose index scan,但在5.1的版本中,mysql中还没办法 直接支持这一优化技术):

| count(distinct nick) |

可是须要通过改写sql来达到伪loose index scan:

+—-+————-+——————————+——-+—————+————-

优化写法:

+—-+————-+——————————+——-+—————+————-

root@db 09:41:10>explain select distinct(nick) from user_access-> ;

1 row in set (5.81 sec)

root@db 09:41:400>select count(*) from ( select distinct(nick) from user_access)t ;

.我 歌词 现在的sql:select count(distinct nick) from user_access;则是直接从nick1刚结束了了每根条扫描下来,直到扫描到最后有有一有1个nick_n,

现在须要换有并不是思路来处理该什么的问题:

root@db 09:42:55>explain select count(distinct nick) from user_access;

Sql中先选出不同的nick,最后在外面套一层,就都还可否得到nick的distinct值总和;

这条sql用于统计用户访问的uv,原应单表的数据量在10G以上,即使在user_access_xx_xx上再加nick的索引,

|               4006934 |

|  1 | SIMPLE      | user_access | range | NULL          | ind_user_access_nick | 67      | NULL | 2124695 | Using index for group-by |

上篇中.我 歌词 提到用伪loose index scan来优化max/min,这一篇.我 歌词 将用伪loose index scan来优化distinct:

+—-+————-+——————————+——-+—————+————-

有另有有一有1个的有有一有1个需求:select count(distinct nick) from user_access_xx_xx;

通过查看执行计划,也为全索引扫描,sql在执行的时候,会对整个服务器带来抖动;

|  1 | SIMPLE      | user_access | index | NULL          | ind_user_access | 177     | NULL | 19546123 | Using index |

| count(*) |