环境:

表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/

MYSQL: Handler_read_%参数说明的更多相关文章

  1. MySql配置参数很全的Mysql配置参数说明

    MySql配置参数 很全的Mysql配置参数说明 1. back_log 指定MySQL可能的连接数量.当MySQL主线程在很短的时间内得到非常多的连接请求,该参数就起作用,之后主线程花些时间(尽管很 ...

  2. mysql CMAKE 参数说明

    MySQL自5.5版本以后,就开始使用CMake编译工具了,因此,你在安装源文件中找不到configure文件是正常的.很多人下到了新版的MySQL,因为找不到configure文件,不知道该怎么继续 ...

  3. MySQL 启动参数说明及性能优化建议

    [mysqld] port = 3306 serverid = 1 socket = /tmp/mysql.sock skip-name-resolve #禁止MySQL对外部连接进行DNS解析,使用 ...

  4. MySQL slave_exec_mode 参数说明

    背景: 今天无意当中看到参数slave_exec_mode,从手册里的说明看出该参数和MySQL复制相关,是可以动态修改的变量,默认是STRICT模式(严格模式),可选值有IDEMPOTENT模式(幂 ...

  5. MySQL配置参数说明

    MYSQL服务器my.cnf配置参数详解: 硬件:内存16G [client] port = 3306 socket = /data/mysql.sock [mysql] no-auto-rehash ...

  6. mysql 部分参数说明

    log_timestamps [5.7] This variable was added in MySQL 5.7.2. Before 5.7.2, timestamps in log message ...

  7. MySQL常用参数说明(持续更新)

      ##innodb correlate   innodb_flush_log_at_trx_commit value: 0,[1],2 effect: control the flush opera ...

  8. CentOS 7 安装 配置 MySQL

    第一部分:CentOS 7安装MySQL 5.7 1.下载YUM库 shell > wget http://dev.mysql.com/get/mysql57-community-release ...

  9. MySQL 第一篇

    一.MySQL介绍 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数 ...

随机推荐

  1. (转载)OC学习篇之---Foundation框架中的NSString对象和NSMutableString对象

    在之前的一篇文章中我们说到了Foundation框架中的NSObject对象,那么今天在在来继续看一下Foundation框架中的常用对象:NSString和NSMutableString. 在OC中 ...

  2. 图解WPF程序打包全过程

    首先打开已经完成的工程,如图: 下面开始制作安装程序包. 第一步:[文件]——[新建]——[项目]——安装项目. 名称——可以自己根据要求修改. 位置——是指你要制作的安装文件存放在什么目录内,可以根 ...

  3. linux3.0.4编译LDD中的scull全过程

    按照惯例,我是应该先写一些本章的收获的,不过太晚了. 在看完第三章之后开始编译,错误一堆,几乎崩溃,幸亏经过不断的百度,总算解决了问题,我发现 我遇到问题比较多,算是集中七个龙珠了吧,感谢先行的大神们 ...

  4. 50+ 响应式的Prestashop电商主题

    PrestaShop是一款针对web2.0设计的全功能.跨平台的免费开源电子商务解决方案,自08年1.0版本发布,短短两年时间,发展迅速,全球已超过四万家网店采用Prestashop进行部署.Pres ...

  5. 【Android】使用persist属性来调用脚本文件

    Android系统中有许多属性,属性由两个部分组成:name & value,可以使用这些属性来记录系统设置或进程之间的信息交换.Android系统在启动过程时会按序从以下几个文件中加载系统属 ...

  6. (翻译)从底层了解ASP.NET体系结构 [转]

    转自:http://www.cnblogs.com/rijing2004/archive/2007/09/14/howaspnetwork.html 前言 关于ASP.NET的底层的工作机制,最近园子 ...

  7. 基于mapreduce的大规模连通图寻找算法

    基于mapreduce的大规模连通图寻找算法 当我们想要知道哪些账号是一个人的时候往往可以通过业务得到两个账号之间有联系,但是这种联系如何传播呢? 问题 已知每个账号之间的联系 如: A B B C ...

  8. KM算法详解+模板

    http://www.cnblogs.com/wenruo/p/5264235.html KM算法用来求二分图最大权完美匹配. 本文配合该博文服用更佳:趣写算法系列之--匈牙利算法 现在有N男N女,男 ...

  9. Java ClassLoader 原理详细分析

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  10. c++builder 重载WindowProc、WndProc 截获消息

    c++builder 重载WindowProc.WndProc 截获消息 方法一WindowProc void __fastcall  myWindowProc(Messages::TMessage ...