您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的

时间:2020-04-07 12:06:38  来源:  作者:

一个索引提高600倍查询速度?

首先准备一张books表

create table books(
    id int not null primary key auto_increment,
    name varchar(255) not null,
    author varchar(255) not null,
    created_at datetime not null default current_timestamp,
    updated_at datetime not null default current_timestamp on update current_timestamp
)engine=InnoDB;

然后插入100w条数据

drop procedure prepare_data;
delimiter //
create procedure prepare_data()
begin
    declare i int;
    set i = 0;
    while i < 1000000
        do
            insert into books(name, author) value (concat('name', i), concat('author', i));
            set i = i + 1;
        end while;
end //
delimiter ;
call prepare_data();

那么问题来了,现在我们要在这100w本书中找到name为name9000000的书,来看看大概需要多久。

set profiling = 1;
select * from books where name = 'name900000';
show profiles;
set profiling = 0;
带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的

 

(图一)

大概在400ms左右,我不是很满意这个查询的速度,那么如何提升查询速度呢?建个索引吧!

create index idx_books_name on books(name);

创建索引后我们再看看查询的速度

set profiling = 1;
select * from books where name = 'name900000';
show profiles;
set profiling = 0;
带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的

 

(图二)

可以发现,只需要6ms,索引为我们带来600倍的速度提升,那么为什么索引可以带来这么大的查询速度提升呢?

索引揭秘

想象一下, 现在我们有100w条数据,如何快速的通过name找到符合条件的数据

如果这100w条数据是按照name有序排列的,那么我们就可以使用二分搜索,这样每次可以排除一半数据。那么100w数据最多只需要查询

带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的

 

~=%2020次就可以找到

运行过程类型下图

 

(图三)

这里可以发现一个问题,在比较过程中,我们只用到了name字段,但是却需要把name和其他字段一起加载到内存,这样显然会浪费很多内存,所以我们可以修改结构为下图

带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的

 

(图四)

我们把原来表中的name和id字段进行一份复制形成了一个新的表,这样的话,当我们根据name来查询数据时,只需要把name和id两个数据加载到内存就行了,当找到数据后再根据id找到对应行的其他数据。

其实这个冗余表就是我们常说的索引,索引表会把我们指定的列的数据进行拷贝形成一个新的表,这个表中的数据是有序排列的,如果有多列,则是按声明的前后关系依次比较。

例如,有一个商品表items,其中有名称、价格、创建日期等字段

create table items
(
    id int not null primary key auto_increment,
    title varchar(255) not null,
    price decimal(12,2) not null,
    created_at datetime not null,
    updated_at datetime not null
) engine = innodb;

(图五)

由于用户喜欢按价格和创建时间查找商品,我们可以创建一个idx_items_price_created_at(price, created_at)的索引,那么他的数据结构就是这样的:先按price排序,再按created_at排序,如图六

带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的

 

(图六)

通过图六的数据结构我们可以学习到索引使用的一个原则和一个优化

一个原则:最左匹配原则:如果要触发索引使用,需要按索引字段的声明顺序来添加条件过滤

以items表中的idx_items_price_created_at索引使用举例:

# sql1:price + created_at条件,可以使用索引
select * from items where price = "20" and created_at = '2020-01-04';

# sql2:created_at + price条件,可以使用索引,注意虽然此处查询条件顺序和索引顺序不一样,但其实MySQL在执行sql前,会先对sql进行语法分析,最终的结果是和sql1一样的。但是我不推荐这种写法,因为对于看代码的人来说没有sql1直观。
select * from items where created_at = "2020-01-04" and price = "20";

# sql3:price 可以使用索引,因为索引表即使只考虑price字段,顺序也是有序的
select * from items where price = "20";

# sql4:crated_at 不可以使用索引,因为索引中如果只考虑craeted_at字段,顺序不能保证有序
select * from items where created_at = "2020-01-04";    

一个优化:覆盖索引:如果要查询的字段全在索引上,那么不需要回表

以items表中的idx_items_price_created_at索引使用举例:

# sql1:由于需要所有的字段,该查询在根据idx_items_price_created_at找到id后,还需要根据id再找items表中该条记录的其他字段的值
select * from items where price = "20" and created_at = '2020-01-04';
​
# sql2: 由于需要的字段在索引上都有,该查询只需要在idx_items_price_created_at索引表找到记录直接返回即可
select price, created_at, id  where price = "20" and created_at = '2020-01-04';

小结

通过本章学习,我们了解到索引其实就是一个有序排列的表,我们通过有序排列的优势来加快查询。也正是由于索引是有序排列的,如果想有效使用索引,我们就需要要遵循最左匹配原则。我们还了解到覆盖索引,如果查询的字段全在索引上,可以减少一次回表查询,利用该特性在大批量查询时可以大幅度优化性能。

本章所讲的内容全是以数据全在内存中为前提的,但是真实场景中数据都是在硬盘中保存,如果一个表中的数据可能有好几G,我们不可能把所有的数据都加载到内存然后进行二分搜索,所以下次我会讲一讲索引和硬盘的关系。



Tags:MySQL 索引   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
什么是索引?索引是数据库快速找到记录行的一种数据结构,类似我们看书时的目录,它是良好性能的关键因素。尤其是表中的数据量越来越大时,如果索引使用不当,会严重影响性能。索引也...【详细内容】
2021-02-25  Tags: MySQL 索引  点击:(189)  评论:(0)  加入收藏
在冯小刚冯导作为导演拍摄的《天下无贼》中有一句经典台词,那就是出自葛优之口:21世纪什么最贵?人才!从这句话说出到现在,已经16年过去了,那么在现在这个大数据时代,什么最贵呢?那...【详细内容】
2020-12-30  Tags: MySQL 索引  点击:(131)  评论:(0)  加入收藏
一、高性能索引1、查询性能问题在MySQL使用的过程中,所谓的性能问题,在大部分的场景下都是指查询的性能,导致查询缓慢的根本原因是数据量的不断变大,解决查询性能的最常见手段是...【详细内容】
2020-08-03  Tags: MySQL 索引  点击:(62)  评论:(0)  加入收藏
概述随着电商的发展,使用数据库的业务越来越复杂,除了掌握哪些场景可以使用索引,哪些场景适合使用索引,还需要掌握索引在运行过程中的一些使用规则,特别是组合索引的使用。比如索...【详细内容】
2020-07-06  Tags: MySQL 索引  点击:(54)  评论:(0)  加入收藏
一个索引提高600倍查询速度?首先准备一张books表create table books( id int not null primary key auto_increment, name varchar(255) not null, author varchar(...【详细内容】
2020-04-07  Tags: MySQL 索引  点击:(74)  评论:(0)  加入收藏
我会谈谈对于索引结构我自己的看法,以及分享如何从零开始一层一层向上最终理解索引结构。从一个简单的表开始createtableuser(idintprimarykey,ageint,heightint,weightint...【详细内容】
2019-12-26  Tags: MySQL 索引  点击:(117)  评论:(0)  加入收藏
学习索引,主要是写出更快的sql,当我们写sql的时候,需要明确的知道sql为什么会走索引?为什么有些sql不走索引?sql会走那些索引,为什么会这么走?我们需要了解其原理,了解内部具体过程,...【详细内容】
2019-12-24  Tags: MySQL 索引  点击:(75)  评论:(0)  加入收藏
前言为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字段的意义。助你了...【详细内容】
2019-10-29  Tags: MySQL 索引  点击:(101)  评论:(0)  加入收藏
索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),它们 包含着对数据表里所有记录的引用指针。普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是...【详细内容】
2019-10-11  Tags: MySQL 索引  点击:(180)  评论:(0)  加入收藏
MySQL凭借着出色的性能、低廉的成本、丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库。虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程...【详细内容】
2019-09-12  Tags: MySQL 索引  点击:(131)  评论:(0)  加入收藏
▌简易百科推荐
作者:雷文霆 爱可生华东交付服务部 DBA 成员,主要负责Mysql故障处理及相关技术支持。爱好看书,电影。座右铭,每一个不曾起舞的日子,都是对生命的辜负。 本文来源:原创投稿 *爱可生...【详细内容】
2021-12-24  爱可生    Tags:MySQL   点击:(7)  评论:(0)  加入收藏
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章...【详细内容】
2021-12-14  python数据分析    Tags:MySQL记录锁   点击:(18)  评论:(0)  加入收藏
binlog 基本认识 MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二...【详细内容】
2021-12-14  linux上的码农    Tags:mysql   点击:(13)  评论:(0)  加入收藏
为查询优化你的查询 大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查...【详细内容】
2021-12-09  元宇宙iwemeta    Tags:mysql   点击:(15)  评论:(0)  加入收藏
测试的目的和原因,公司有很多程序员,每个程序员对数据库和表结构都有自己的理解。而且每个程序员的理解往往是以效率考虑。既然都是为了效率考虑,那么我就来测试一下究竟哪种使...【详细内容】
2021-12-08  吴彬的分享    Tags:Mysql数据库   点击:(14)  评论:(0)  加入收藏
当你们考虑项目并发的时候,我在部署环境,当你们在纠结使用ArrayList还是LinkedArrayList的时候,我还是在部署环境。所以啊,技术不止境,我在部环境。今天这篇文章缕一下在同一台服...【详细内容】
2021-12-08  秃头码哥    Tags:MySQL数据库   点击:(17)  评论:(0)  加入收藏
对于数据分析来说,MySQL使用最多的是查询,比如对数据进行排序、分组、去重、汇总及字符串匹配等,如果查询的数据涉及多个表,还需要要对表进行连接,本文就来说说MySQL中常用的查询...【详细内容】
2021-12-06  笨鸟学数据分析    Tags:MySQL   点击:(21)  评论:(0)  加入收藏
在学习SQL语句之前,首先需要区分几个概念,我们常说的数据库是指数据库软件,例如MySQL、Oracle、SQL Server等,而本文提到的数据库是指数据库软件中的一个个用于存储数据的容器。...【详细内容】
2021-11-24  笨鸟学数据分析    Tags:SQL语句   点击:(23)  评论:(0)  加入收藏
概述以前参加过一个库存系统,由于其业务复杂性,搞了很多个应用来支撑。这样的话一份库存数据就有可能同时有多个应用来修改库存数据。比如说,有定时任务域xx.cron,和SystemA域...【详细内容】
2021-11-05  Java云海    Tags:分布式锁   点击:(31)  评论:(0)  加入收藏
MySQL的进阶查询 一、 按关键字排序 使用ORDERBY语句来实现排序排序可针对一个或多个字段ASC:升序,默认排序方式 【升序是从小到大】DESC:降序 【降序是从大到小】ORDER BY的...【详细内容】
2021-11-05  Java热点    Tags:SQL语句   点击:(28)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条