• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    一个案例彻底弄懂如何正确使用mysql inndb联合索引

    有一个业务是查询最新审核的5条数据

    SELECT `id`, `title`
    FROM `th_content`
    WHERE `audit_time`  1541984478
     AND `status` = 'ONLINE'
    ORDER BY `audit_time` DESC, `id` DESC
    LIMIT 5;

    查看当时的监控情况 cpu 使用率是超过了100%,show processlist看到很多类似的查询都是处于create sort index的状态。

    查看该表的结构

    CREATE TABLE `th_content` (
     `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
     `title` varchar(500) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '内容标题',
     `content` mediumtext CHARACTER SET utf8 NOT NULL COMMENT '正文内容',
     `audit_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '审核时间',
     `last_edit_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最近编辑时间',
     `status` enum('CREATED','CHECKING','IGNORED','ONLINE','OFFLINE') CHARACTER SET utf8 NOT NULL DEFAULT 'CREATED' COMMENT '资讯状态',
     PRIMARY KEY (`id`),
     KEY `idx_at_let` (`audit_time`,`last_edit_time`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    索引有一个audit_time在左边的联合索引,没有关于status的索引。

    分析上面的sql执行的逻辑:

    最后因为数据量很大,虽然只取5行,但是按照我们刚刚举的极端例子,实际查询了100万行数据,而且最后还在内存中进行了50万行数据库的内存排序。

    所以是非常低效的。

    画了一个示意图,说明第一步的查询过程,粉红色部分表示最后需要回表查询的数据行。

    图中我按照索引存储规律来YY伪造填充了一些数据,如有不对请留言指出。希望通过这张图大家能够看到联合索引存储的方式和索引查询的方式

    改进思路 1

    范围查找向来不太好使用好索引的,如果我们增加一个audit_time, status的联合索引,会有哪些改进呢?

    ALTER TABLE `th_content` ADD INDEX `idx_audit_status` (`audit_time`, `status`);
    mysql> explain select `id`, `title` from `th_content` where `audit_time`  1541984478 and `status` = 'ONLINE' order by `audit_time` desc, `id` desc limit 5;
    +----+-------------+------------+-------+------------------------------------------+------------------+---------+------+--------+-------------+
    | id | select_type | table  | type | possible_keys       | key    | key_len | ref | rows | Extra  |
    +----+-------------+------------+-------+------------------------------------------+------------------+---------+------+--------+-------------+
    | 1 | SIMPLE  | th_content | range | idx_at_ft_pt_let,idx_audit_status  | idx_audit_status | 4  | NULL | 209754 | Using where |
    +----+-------------+------------+-------+------------------------------------------+------------------+---------+------+--------+-------------+

    细节:因为audit_time是一个范围查找,所以第二列的索引用不上了,只能用到audit_time,所以key_len是4。而下面思路2中,还是这两个字段key_len则是5。

    还是分析下在添加了该索引之后的执行过程:

    在上面的示意图中,粉红色标识满足第一列索引要求的行,依次向前查询,本个叶子节点上筛选到了3条记录,然后需要继续向左,到前一个叶子节点继续查询。直到找到5条满足记录的行,最后回表。

    改进之处

    因为在索引里面有status的值,所以在筛选满足status='ONLINE'行的时候,就不用回表查询了。在回表的时候只有5行数据的查询了,在iops上会大大减少。

    该索引的弊端

    如果idx_audit_status里扫描5行都是statusONLINE,那么只需扫描5行;

    如果idx_audit_status里扫描前100万行中,只有4行statusONLINE,则需要扫描100万零1行,才能得到需要的5行记录。索引需要扫描的行数不确定。

    改进思路 2

    ALTER TABLE `th_content` DROP INDEX `idx_audit_status`;
    ALTER TABLE `th_content` ADD INDEX `idx_status_audit` (`status`, `audit_time`);

    这样不管是排序还是回表都毫无压力啦。

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

    您可能感兴趣的文章:
    • mysql的联合索引(复合索引)的实现
    • MySQL全文索引、联合索引、like查询、json查询速度哪个快
    • 深入浅析Mysql联合索引最左匹配原则
    • MySQL联合索引功能与用法实例分析
    • MySQL联合索引用法示例
    • MySQL中的联合索引学习教程
    • MySQL 联合索引与Where子句的优化 提高数据库运行效率
    • MySQL 独立索引和联合索引的选择
    上一篇:GDB调试Mysql实战之源码编译安装
    下一篇:MySQL新建用户中的%到底包不包括localhost?
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    一个案例彻底弄懂如何正确使用mysql inndb联合索引 一个,案例,彻底,弄懂,如何,