mysql handler read_MYSQL: Handler_read_%参数说明

环境:

表t_feed_idx(user_id bigint, feed_id bigint, KEY (`user_id`,`feed_id`)) engine=innodb;

表t_feed_info(feed_id bigint, PRIMARY KEY (`feed_id`), '其他列') engine=innodb;

feed 总数 : 100000

用户(ID:20000001) feed 数 : 200

查询

#########  单表

> 全部扫描

EXPLAIN SELECT * FROM `t_feed_info` AS i ORDER BY NULL LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    ALL    \\N    \\N    \\N    \\N    98734

Handler_read_first + 1 : 从(主)键的第一个位置开始读取

Handler_read_key + 1 : 根据第一个位置的KEY读1行,其他9行是根据叶节点的链表依次读取

Handler_read_rnd_next +10 : 从主键的叶节点(行数据)中顺序读取10行

> 索引扫描

EXPLAIN SELECT * FROM `t_feed_info` AS i ORDER BY feed_id LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    index    \\N    PRIMARY    8    \\N    10

Handler_read_first + 1 : 从(主)键的第一个位置开始读取

Handler_read_key + 1 : 根据第一个位置的KEY读1行

Handler_read_next + 9 : 按(主)键顺序依次读取之后的9行

EXPLAIN SELECT * FROM `t_feed_info` AS i ORDER BY feed_id DESC LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    index    \\N    PRIMARY    8    \\N    10

Handler_read_key + 1 : 根据第一个位置的KEY读1行

Handler_read_last + 1 : 从(主)键的最后一个位置开始读取

Handler_read_prev + 9 : 按(主)键顺序依次读取之前的9行

> 索引覆盖扫描

EXPLAIN SELECT feed_id FROM `t_feed_info` AS i ORDER BY feed_id LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    index    \\N    PRIMARY    8    \\N    10    Using index

Handler_read_first + 1 : 从(主)键的第一个位置开始读取

Handler_read_key + 1 : 根据第一个位置的KEY读1行

Handler_read_next + 9 : 按(主)键顺序依次读取之后的9行

EXPLAIN SELECT feed_id FROM `t_feed_info` AS i ORDER BY feed_id DESC LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    index    \\N    PRIMARY    8    \\N    10    Using index

Handler_read_key + 1 : 根据第一个位置的KEY读1行

Handler_read_last + 1 : 从(主)键的最后一个位置开始读取

Handler_read_prev + 9 : 按(主)键倒序依次读取之后的9行

############### join

# set @uid := '20000001';

> WHERE + 排序

# asc

EXPLAIN SELECT * FROM `t_feed_idx` AS i

LEFT JOIN `t_feed_info` AS f ON f.`feed_id`=i.`feed_id`

WHERE i.user_id=@uid ORDER BY i.feed_id LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    ref    user_id    user_id    8    const    200    Using where; Using index

1    SIMPLE    f    eq_ref    PRIMARY    PRIMARY    8    z3.i.feed_id    1

Handler_read_key + 11 : t_feed_idx 根据user_id读1次,t_feed_info根据feed_id读10次

Handler_read_next + 9 : t_feed_idx按键顺序依次向后读取9个feed_id

# desc

EXPLAIN SELECT * FROM `t_feed_idx` AS i

LEFT JOIN `t_feed_info` AS f ON f.`feed_id`=i.`feed_id`

WHERE i.user_id=@uid ORDER BY i.feed_id desc LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    ref    user_id    user_id    8    const    200    Using where; Using index

1    SIMPLE    f    eq_ref    PRIMARY    PRIMARY    8    z3.i.feed_id    1

Handler_read_key + 11 : t_feed_idx 根据user_id读1次,t_feed_info根据feed_id读10次

Handler_read_prev + 9 : t_feed_idx按键倒序依次向前读取9个feed_id

# 不好的查询方式:

> 使用被关联表t_feed_info的feed_id列进行排序

EXPLAIN SELECT * FROM `t_feed_idx` AS i

LEFT JOIN `t_feed_info` AS f ON f.`feed_id`=i.`feed_id`

WHERE i.user_id=@uid ORDER BY f.feed_id LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    ref    user_id    user_id    8    const    200    Using index; Using temporary; Using filesort

1    SIMPLE    f    eq_ref    PRIMARY    PRIMARY    8    z3.i.feed_id    1

Handler_read_key + 201 : t_feed_idx 根据user_id读1次,t_feed_info根据feed_id读200次

Handler_read_next + 200 : t_feed_idx按键顺序依次读取199个feed_id. 额外的1次是??

Handler_read_rnd + 10 : filesort后每行位置都是固定的,limit 10取10行

Handler_read_rnd_next + 201: filesort全表遍历读取temporary表中的200行,进行排序; 额外的1是EOF标志位;

Using temporary; Using filesort 原因: 无法使用t_feed_idx表的索引

1>先查询表t_feed_idx中满足@uid的200行与表t_feed_info进行join,将结果保存在temporary表

Handler_read_key + 201, Handler_read_next + 200

2>然后对临时表排序;

Handler_read_rnd_next + 201

3>取前10个。

Handler_read_rnd + 10

> where条件放在join中

EXPLAIN SELECT * FROM `t_feed_idx` AS i

LEFT JOIN `t_feed_info` AS f ON f.`feed_id`=i.`feed_id` AND i.user_id=@uid

ORDER BY i.`feed_id` DESC LIMIT 0, 10;

点击(此处)折叠或打开

id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra

1    SIMPLE    i    index    \\N    user_id    16    \\N    100396    Using index; Using filesort

1    SIMPLE    f    eq_ref    PRIMARY    PRIMARY    8    z3.i.feed_id    1

Handler_read_first + 1 : 从表t_feed_idx 中user_id索引开始位置进行读取

Handler_read_key + 11 : t_feed_idx 根据user_id读1次,t_feed_info根据feed_id读10次

Handler_read_rnd_next + 100001: filesort全表遍历读取表t_feed_idx 中user_id索引的100000行,进行排序; 额外的1是EOF标志位;

没有 Using temporary 是因为先对t_feed_idx的索引user_id进行排序,然后再join

Using filesort 原因:

无法使用t_feed_idx表的索引

1>先对表t_feed_idx排序,取10个feed_id

Handler_read_first + 1, Handler_read_key + 1, Handler_read_rnd_next + 100001

2>然后根据feed_id与表t_feed_info进行join

Handler_read_key + 10

参考: http://www.mysqlperformanceblog.com/2010/06/15/what-does-handler_read_rnd-mean/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值