zoukankan      html  css  js  c++  java
  • 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 1    SIMPLE    i    ref    user_id    user_id    8    const    200    Using where; Using index
    3. 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;

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 1    SIMPLE    i    ref    user_id    user_id    8    const    200    Using where; Using index
    3. 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;  

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 1    SIMPLE    i    ref    user_id    user_id    8    const    200    Using index; Using temporary; Using filesort
    3. 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;  

    点击(此处)折叠或打开

    1. id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
    2. 1    SIMPLE    i    index    \N    user_id    16    \N    100396    Using index; Using filesort
    3. 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/
  • 相关阅读:
    复制表部分内容到另一个表
    delphi使用ODAC控件TOraQuery操作表数据
    delphi使用ODAC控件查询存储过程返回结果集
    delphi使用ODAC控件事务处理(缓存提交)
    delphi使用ODAC控件事务处理(自动提交)
    delphi使用ODAC控件异步读取数据
    delphi使用ODAC控件常用功能
    delphi使用ODAC控件操作本地数据集
    时间限制关闭窗体的几点体会
    一个简单的双缓冲队列
  • 原文地址:https://www.cnblogs.com/zengkefu/p/5685793.html
Copyright © 2011-2022 走看看