Mysql延迟关联和索引覆盖

Posted faker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql延迟关联和索引覆盖相关的知识,希望对你有一定的参考价值。

之前做过对过延迟关联以及索引覆盖的测试,当时没有记录起来,导致后面回想起来总是忘记一些细枝末节。今天趁着心血来潮重新回顾一下当时的测试结果。

以下是建表语句:

CREATE TABLE `human` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT \'主键\',
  `name` varchar(50) NOT NULL DEFAULT \'\' COMMENT \'姓名\',
  `age` int(11) NOT NULL DEFAULT \'0\' COMMENT \'年龄\',
  `sex` tinyint(4) NOT NULL DEFAULT \'0\' COMMENT \'性别\',
  `occupation` int(11) NOT NULL DEFAULT \'0\' COMMENT \'职业\',
  `education` int(11) NOT NULL DEFAULT \'0\' COMMENT \'学历\',
  `birthday` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT \'生日\',
  `city` varchar(20) NOT NULL DEFAULT \'\' COMMENT \'所在城市\',
  `adress` varchar(100) NOT NULL DEFAULT \'\' COMMENT \'详细地址\',
  `town` varchar(30) NOT NULL DEFAULT \'\' COMMENT \'镇\',
  `village` varchar(30) NOT NULL DEFAULT \'\' COMMENT \'村\',
  `province` varchar(20) NOT NULL DEFAULT \'\' COMMENT \'省份\',
  `district` varchar(20) NOT NULL DEFAULT \'\' COMMENT \'区\',
  PRIMARY KEY (`id`),
  KEY `name` (`name`),
  KEY `district` (`district`) USING BTREE,
  KEY `province_district` (`province`,`district`) USING BTREE,
  KEY `city` (`city`,`town`,`village`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=13765413 DEFAULT CHARSET=utf8;  

自己写了一个灌入数据的web demo,通过http请求来进行数据灌入。github地址:https://github.com/Mingo-xoto/IndexTestDemo ,接口类名:com.yhq.web.controller.TestController

记录数为:13586901

建立的索引如下:

1、索引覆盖

 

select id,city from human where city=\'广州市\' limit 10000,10;

或者

select id,city,town, village from human where city=\'广州市\' limit 10000,10;

基本都是0.00几秒的级别

由于我建立了一个 city, town, village 的复合索引,索引mysql查询索引就可以直接返回结果而不需要进行回表查询具体列,但假如需要查询不在该复合索引的列的时候,就需要回表操作了。

select id,city,town, village,province from human where city=\'广州市\' limit 10000,10;

需要46.637秒才能得到结果。

2、延迟关联

传统写法查询10000页后的10条记录:select * from human where city=\'广州市\' limit 10000,10;耗时将近1分钟

使用延迟关联之后:0.004s, 质的提升!

select * from human h INNER JOIN
(
select id,city from human where city=\'广州市\' limit 10000,10
) as a on a.id=h.id;

或者

select * from human h INNER JOIN
(
select id,city from human where city=\'广州市\' limit 10000,10
) as a using(id);

两种都行,测试了好像也没什么区别。

 

至于为什么提升这么快,在《高性能MySQL》有提到(图片是直接引用别人博客的 :http://blog.csdn.net/u012817635/article/details/52277490):

 

 

 

第一次在博客园写博客,梳理的知识可能也不是很准确,只是作为个人的一个学习记录。

以上是关于Mysql延迟关联和索引覆盖的主要内容,如果未能解决你的问题,请参考以下文章

延迟关联的一次粗浅使用

Mysql索引explain执行计划

Mysql多表关联查询,有索引和没索引的差距

片段未与片段管理器关联。 (对话片段)

高性能mysql 4,5,6章优化总结

mysql覆盖索引和联合索引的区别