深入理解InnoDB(4)—索引使用

1. 索引的代价

在了解索引的代价之前,需要再次回顾一下索引的数据结构B+树

image.png

如上图,是一颗b+树,关于b+树的定义可以参见B+树,这里只说一些重点,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

1.1 b+树的查找过程

如图所示,如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。

空间上的代价

从索引的数据结构可以得出,每建立一个索引都要为它建立一棵B+树,每一棵B+树的每一个节点都是一个数据页,一个页默认会占用16KB的存储空间,一棵很大的B+树由许多数据页组成,那可是很大的一片存储空间呢。

时间上的代价

每次对表中的数据进行增、删、改操作时,都需要去修改各个B+树索引。而且我们讲过,B+树每层节点都是按照索引列的值从小到大的顺序排序而组成了双向链表。不论是叶子节点中的记录,还是内节点中的记录(也就是不论是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序而形成了一个单向链表。而增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间进行一些记录移位,页面分裂、页面回收啥的操作来维护好节点和记录的排序。

1.2 什么时候要使用索引?

只要使用到索引都是有代价的,因此我们不能盲目的使用索引

  • 主键自动建立主键索引
  • 频繁作为查询条件在WHERE
  • 查询中与其他表关联的字段,外键关系建立索引
  • 作为排序的列要建立索引,排序字段通过索引去访问,会大大提高排序速度
  • 高并发条件下倾向组合索引;
  • 查询中统计或者分组的字段或者用于聚合函数的列可以建立索引,例如使用了max(column_1)或者count(column_1)时的column_1就需要建立索引

1.3 什么时候尽量不要建立索引

  • 表记录太少(全表扫描也很快,没有必要)
  • 经常增删改的字段上不要建立索引
  • 有大量重复且分布均匀的数据的列不建立索引

2. 多列索引

在上面的例子中,都是以单个列作为索引的

而多列索引指的是组合索引,组合多个列创建一个索引,很多人对多列索引理解不够,常见的就是为每一个列创建独立的索引,或者按照错误的顺序创建组合索引。

在多个列上建立单列索引大部分情况下并不能提高MySQL的查询性能。MySQL5.0和更新的版本引入了一种“索引合并”(index merge)的策略,一定程度上可以使用表上的多个单列索引来定位指定的行。

在MySQL’更早的版本中只能使用其中某一个单列索引。但在MySQL5.0和更新的版本中,查询能够同时使用多个单列索引进行扫描,并将结果进行合并
该特新主要应用于以下三种场景:

  1. 对OR语句求并集,如查询SELECT * FROM TB1 WHERE c1=“xxx” OR c2="“xxx"时,如果c1和c2列上分别有索引,可以按照c1和c2条件进行查询,再将查询结果合并(union)操作,得到最终结果
  2. 对AND语句求交集,如查询SELECT * FROM TB1 WHERE c1=“xxx” AND c2=”"xxx"时,如果c1和c2列上分别有索引,可以按照c1和c2条件进行查询,再将查询结果取交集(intersect)操作,得到最终结果
  3. 对AND和OR组合语句求结果

2.1 索引适用的查询

  • 全值匹配
    如果我们的搜索条件中的列和索引列一致的话,这种情况就称为全值匹配

  • 匹配左边的列
    其实在我们的搜索语句中也可以不用包含全部联合索引中的列,只包含左边的就行

  • 匹配列前缀
    对于字符串类型的索引列来说,我们只匹配它的前缀也是可以快速定位记录的

  • 匹配范围值
    b+树的所有记录都是按照索引列的值从小到大的顺序排好序的,所以这极大的方便我们查找索引列的值在某个范围内的记录,不过在使用联合进行范围查找的时候需要注意,如果对多个列同时进行范围查找的话,只有对索引最左边的那个列进行范围查找的时候才能用到B+树索引。

2.2 使用联合索引进行排序注意事项

对于联合索引有个问题需要注意,ORDER BY的子句后边的列的顺序也必须按照索引列的顺序给出

2.3 不可以使用索引进行排序的几种情况

2.3.1 ASC、DESC混用

对于使用联合索引进行排序的场景,我们要求各个排序列的排序顺序是一致的,也就是要么各个列都是ASC规则排序,要么都是DESC规则排序。

2.3.2 排序列包含非同一个索引的列

有时候用来排序的多个列不是一个索引里的,这种情况也不能使用索引进行排序

2.3.3 排序列使用了复杂的表达式

要想使用索引进行排序操作,必须保证索引列是以单独列的形式出现,而不是修饰过的形式

2.4 多列索引分组

如果没有索引的话,分组过程全部需要在内存里实现,而如果有了索引的话,恰巧这个分组顺序又和我们的B+树中的索引列的顺序是一致的,而我们的B+树索引又是按照索引列排好序的,这不正好么,所以可以直接使用B+树索引进行分组。

2.5 回表的代价

查询优化器会事先对表中的记录计算一些统计数据,然后再利用这些统计数据根据查询的条件来计算一下需要回表的记录数,需要回表的记录数越多,就越倾向于使用全表扫描,反之倾向于使用二级索引 + 回表的方式。一般情况下,限制查询获取较少的记录数会让优化器更倾向于选择使用二级索引 + 回表的方式进行查询,因为回表的记录越少,性能提升就越高

2.6 覆盖索引

为了彻底告别回表操作带来的性能损耗,我们建议:最好在查询列表里只包含索引列。

2.6.1 覆盖索引是非常有用的工具,能够极大的提高性能

索引条目通常远远小于数据行操作,索引如果只需要读取索引,那么MySQL就会极大的减少数据访问量
因为索引是按照列值顺序存储的(至少单个页内如此),所以对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少的多

一些存储引擎如MyISAM的内存中只缓存索引,数据则依赖操作系统来缓存,因此访问数据需要一次系统调用。这会导致严重的性能问题

由于InnoDB的聚簇索引,覆盖索引对于InnoDB表特别有用。由于InnoDB的二级索引在叶子结点中保存了行的主键值,如果二级主键能够覆盖查询,则可以便面对主键索引的二次查询

注意:不是所有的索引都可以成为覆盖索引,覆盖索引必须要存储索引列的值,索引哈希索引、空间索引、全文索引的都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引

3. 如何挑选索引

3.1 只为用于搜索、排序或分组的列创建索引

只为出现在WHERE子句中的列、连接子句中的连接列,或者出现在ORDER BY或GROUP BY子句中的列创建索引。而出现在查询列表中的列就没必要建立索引了

3.2 考虑列的基数

列的基数指的是某一列中不重复数据的个数,比方说某个列包含值2, 5, 8, 2, 5, 8, 2, 5, 8,虽然有9条记录,但该列的基数却是3。也就是说,在记录行数一定的情况下,列的基数越大,该列中的值越分散,列的基数越小,该列中的值越集中。这个列的基数指标非常重要,直接影响我们是否能有效的利用索引。假设某个列的基数为1,也就是所有记录在该列中的值都一样,那为该列建立索引是没有用的,因为所有值都一样就无法排序,无法进行快速查找了~ 而且如果某个建立了二级索引的列的重复值特别多,那么使用这个二级索引查出的记录还可能要做回表操作,这样性能损耗就更大了。所以结论就是:最好为那些列的基数大的列建立索引,为基数太小列的建立索引效果可能不好。

3.3 索引列的类型尽量小

如果我们想要对某个整数列建立索引的话,在表示的整数范围允许的情况下,尽量让索引列使用较小的类型,比如我们能使用INT就不要使用BIGINT,能使用MEDIUMINT就不要使用INT~ 这是因为:

数据类型越小,在查询时进行的比较操作越快(这是CPU层次的东东)

数据类型越小,索引占用的存储空间就越少,在一个数据页内就可以放下更多的记录,从而减少磁盘I/O带来的性能损耗,也就意味着可以把更多的数据页缓存在内存中,从而加快读写效率。

3.4 索引字符串值的前缀

只对字符串的前几个字符进行索引也就是说在二级索引的记录中只保留字符串前几个字符。这样在查找记录时虽然不能精确的定位到记录的位置,但是能定位到相应前缀所在的位置,然后根据前缀相同的记录的主键值回表查询完整的字符串值,再对比就好了。这样只在B+树中存储字符串的前几个字符的编码,既节约空间,又减少了字符串的比较时间,还大概能解决排序的问题

  • 优点:这样可以大大节约索引的空间,从而提高索引的效率。
  • 缺点:使用前缀索引会降低索引的选择性,而且无法使用前缀索引做ORDER BY和GROUP BY,也无法使用前缀索引做覆盖扫描

3.4.1 如何选则前缀索引长度

选择前缀的索引的原则是要选择足够的长度保证索引较高的选择性,前缀索引的选择性应该接近于索引的整个列,但同时又不能太长。

可以根据,前缀的基数应该接近于完整列的基数,来确定基数的长度,我们可以通过截取不同长度的字符和完整列进行比较,找到合适的长度
另外一个办法就是计算完整列的选择性,并使用前缀的选择性接近完整列的选择性

3.5 让索引列在比较表达式中单独出现

如果索引列在比较表达式中不是以单独列的形式出现,而是以某个表达式,或者函数调用形式出现的话,是用不到索引的

3.6 主键插入顺序

如果我们插入的记录的主键值是依次增大的话,那我们每插满一个数据页就换到下一个数据页继续插,而如果我们插入的主键值忽大忽小的话,这就比较麻烦了。如果数据页已经满了啊,再插进来咋办呢?我们需要把当前页面分裂成两个页面,把本页中的一些记录移动到新创建的这个页中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391435.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双城记s001_双城记! (使用数据讲故事)

双城记s001Keywords: Data science, Machine learning, Python, Web scraping, Foursquare关键字:数据科学,机器学习,Python,Web抓取,Foursquare https://br.pinterest.com/pin/92816442292506979/https://br.pintere…

web前端面试总结

2019独角兽企业重金招聘Python工程师标准>>> 摘要:前端的东西特别多,面试的时候我们如何从容应对,作为一个老兵,我在这里分享几点我的经验。 一、javascript 基础(es5) 1、原型:这里可以谈很多,…

tableau破解方法_使用Tableau浏览Netflix内容的简单方法

tableau破解方法Are you struggling to perform EDA with R and Python?? Here is an easy way to do exploratory data analysis using Tableau.您是否正在努力使用R和Python执行EDA? 这是使用Tableau进行探索性数据分析的简单方法。 Lets Dive in to know the …

六周第三次课

2019独角兽企业重金招聘Python工程师标准>>> 六周第三次课 9.6/9.7 awk awk也是流式编辑器,针对文档中的行来操作,一行一行地执行。 awk比sed更强大的功能是它支持了分段。 -F选项的作用是指定分隔符,如果不加-F选项,…

macaca web(4)

米西米西滴,吃过中午饭来一篇,话说,上回书说道macaca 测试web(3),参数驱动来搞,那么有小伙本又来给雷子来需求, 登录模块能不能给我给重新封装一下吗, 我说干嘛封装&…

rfm模型分析与客户细分_如何使用基于RFM的细分来确定最佳客户

rfm模型分析与客户细分With some free time at hand in the midst of COVID-19 pandemic, I decided to do pro bono consulting work. I was helping a few e-commerce companies with analyzing their customer data. A common theme I encountered during this work was tha…

数据仓库项目分析_数据分析项目:仓库库存

数据仓库项目分析The code for this project can be found at my GitHub.该项目的代码可以在我的GitHub上找到 。 介绍 (Introduction) The goal of this project was to analyse historic stock/inventory data to decide how much stock of each item a retailer should hol…

web前端效率提升之浏览器与本地文件的映射-遁地龙卷风

1.chrome浏览器,机制是拦截url,      1.在浏览器Element中调节的css样式可以直接同步到本地文件,反之亦然,浏览器会重新加载css,省去刷新   2.在source面板下对js的编辑可以同步到本地文件,反之亦然…

归因分析_归因分析:如何衡量影响? (第2部分,共2部分)

归因分析By Lisa Cohen, Ryan Bouchard, Jane Huang, Daniel Yehdego and Siddharth Kumar由 丽莎科恩 , 瑞安布沙尔 , 黄美珍 , 丹尼尔Yehdego 和 亚洲时报Siddharth库马尔 介绍 (Introduction) This is our second article in a series wh…

linux与磁盘相关的内容

本节所讲内容1.认识SAS-SATA-SSD-SCSI-IDE硬盘2.使用fdisk对磁盘进行操作,分区,格式化3.开机自动挂载分区4.使用parted操作大于等于4T硬盘5.扩展服务器swap内存空间 MBR(Master Boot Record)主引导记录,也就是现有的硬盘分区模式。MBR分区的标…

页面布局

页面布局两大类&#xff1a;   主站&#xff1a; 1 <div classpg-header> 2 <div stylewidth:980px;margin:0 auto;> 3 内容自动居中 4 </div> 5 <div classpg-content></div> 6 <div classpg-footer></div&…

sonar:默认的扫描规则

https://blog.csdn.net/liumiaocn/article/details/83550309 https://note.youdao.com/ynoteshare1/index.html?id3c1e6a08a21ada4dfe0123281637e299&typenote https://blog.csdn.net/liumiaocn/article/details/83550309 文本版&#xff1a; soanr规则java版 …

多变量线性相关分析_如何测量多个变量之间的“非线性相关性”?

多变量线性相关分析现实世界中的数据科学 (Data Science in the Real World) This article aims to present two ways of calculating non linear correlation between any number of discrete variables. The objective for a data analysis project is twofold : on the one …

探索性数据分析(EDA):Python

什么是探索性数据分析(EDA)&#xff1f; (What is Exploratory Data Analysis(EDA)?) If we want to explain EDA in simple terms, it means trying to understand the given data much better, so that we can make some sense out of it.如果我们想用简单的术语来解释EDA&a…

微服务框架---搭建 go-micro环境

1.安装micro 需要使用GO1.11以上版本 #linux 下 export GO111MODULEon export GOPROXYhttps://goproxy.io # windows下设置如下环境变量 setx GO111MODULE on setx GOPROXY https://goproxy.io # 使用如下指令安装 go get -u -v github.com/micro/micro go get -u -v github.co…

写作工具_4种加快数据科学写作速度的工具

写作工具I’ve been writing about data science on Medium for just over two years. Writing, in particular, technical writing can be time-consuming. Not only do you need to come up with an idea, write well, edit your articles for accuracy and flow, and proofr…

python数据结构与算法

2019独角兽企业重金招聘Python工程师标准>>> http://python.jobbole.com/tag/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/ 转载于:https://my.oschina.net/u/3572879/blog/1611369

大数据(big data)_如何使用Big Query&Data Studio处理和可视化Google Cloud上的财务数据...

大数据(big data)介绍 (Introduction) This article will show you one of the ways you can process stock price data using Google Cloud Platform’s BigQuery, and build a simple dashboard on the processed data using Google Data Studio.本文将向您展示使用Google Cl…

ubuntu 16.04常用命令

ip配置&#xff1a; 终端输入vi /etc/network/interfaces命令编辑配置文件,增加如下内容&#xff1a;         auto enp2s0    iface enp2s0 inet static    address 192.168.1.211    netmask 255.255.255.0    gateway 192.168.1.1 重启网卡&#xf…

多元时间序列回归模型_多元时间序列分析和预测:将向量自回归(VAR)模型应用于实际的多元数据集...

多元时间序列回归模型Multivariate Time Series Analysis多元时间序列分析 A univariate time series data contains only one single time-dependent variable while a multivariate time series data consists of multiple time-dependent variables. We generally use mult…