栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

数据库基础

数据库基础

好讲解:索引讲解
好讲解2: MySQL 的覆盖索引与回表 - 张德检的文章

概述 1.1 概念

DDL:DDL(Data Definition Languages)语句:数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象。常用的语句关键字主要包括create、drop、alter等。
DML(Data Manipulation Language)语句:数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性。常用的语句关键字主要包括 insert、delete、update和select等。
DCL(Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括grant、revoke等。

定义1:索引是 帮助MYSQL 高效获取数据的排好序的数据结构。
定义2:索引在mysql中是一种键,是存储引擎用来快速找到记录的一种数据结构。
定义3:数据库只做两件事情:存储数据、检索数据。而索引是在你存储的数据之外,额外保存一些路标(一般是B+树),以减少检索数据的时间。所以索引是主数据衍生的附加结构。
目的:索引的目的在于提高查询效率。

一张表可以建立任意多个索引,每个索引可以是任意多个字段的组合。索引可能会提高查询速度(如果查询时使用了索引),但一定会减慢写入速度,因为每次写入时都需要更新索引,所以索引只应该加在经常需要搜索的列上,不要加在写多读少的列上。

1.2 索引优缺点

优点

  • 大大加快检索速度
  • 加快表与表之间的连接
  • 使用分组group 和排序order字句的时候,可以显著减少查询中分组和排序的时间

    排序查询的sql需求:树形的有序特性,能保持O(log(n))的高效率。

    • 分组:group by
    • 排序:order by
    • 比较<, >

缺点

  • 占用物理空间
  • 创建和维护索引需要花费时间
1.3 索引类型

按照物理地址和逻辑地址是否一致可以分为:聚集索引、非聚集索引(辅助索引、二次索引、普通索引)

  • 聚簇索引:数据存放的物理顺序与逻辑顺序一致。按照主键索引构造B+树(没有就唯一索引、还没有就rowid),树中的叶子节点存放的是所有列的数据,也就是数据所在的物理地址。
  • 非聚簇索引:数据存放的物理顺序与逻辑顺序不一致。按照辅助索引构建B+树,树中存放的是主键的索引值,根据主键和物理地址二次查找(即回表查询)去主键索引树查找数据。

    非聚簇索引(普通索引、二级索引、辅助索引)需要先找到对应索引的主键,再通过主键索引树找到数据,进行二次查找,就叫回表查询

按功能分类

  • 普通索引:它没有任何限制,允许在定义索引的列中插入重复值和空值
  • 唯一索引:索引列的值必须唯一,允许有null值,如果是组合索引,列值的组合必须唯一(空值也只能一个字段有空值)
  • 主键索引:主键索引是一种特殊的唯一索引,一个表只能有一个主键不允许有空值,一般是在创建表的时候指定主键,主键默认就是主键索引
  • 组合索引:多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用
  • 全文索引:通过建立倒排索引,,解决判断字段是否包含的问题。
  • 覆盖索引:一种特殊的联合索引,即你查询的字段所有数据都在索引上,不需要再进行一次回表查询,这样的索引即为覆盖索引。当sql语句的所求查询字段(select列)和查询条件字段(where子句)全都包含在一个索引中(联合索引),可以直接使用索引查询而不需要回表。这就是覆盖索引。

主键索引和普通索引查询

1 select * from t_user where id=1
2 //即主键查询方式,则只需要搜索id这棵B+树
1 select * from t_user where name="张三" 
2 //即普通索引查询方式,则需要先搜索name索引树,得到id的值为3,再到id索引树搜索一次。这个过程称为回表
1.4 聚集索引与非聚集索引

聚簇索引的逻辑顺序,就是数据在硬盘上的物理顺序。一般情况下主键就是默认的聚簇索引。对于经常更新的列不宜建立聚簇索引。

一旦具有第一个索引值的记录被找到,具有连续索引值的记录也一定物理地紧跟其后。

如果一张表上还没有聚簇索引,为它新创建聚簇索引时,就需要对已有数据重新进行排序,所以对表进行修改速度较慢是聚簇索引的缺点

如果有主键就使用主键,没有就使用唯一键,没有唯一键就使用6字节的rowid。

非聚集索引的逻辑顺序与数据爱硬盘上的物理顺序不同。
一张表只允许存在一个聚簇索引,因为真实数据的物理顺序只能有一种。

1.5 不同索引类型 1.5.1 聚集索引与唯一索引

聚簇索引不一定是唯一索引,聚簇索引的索引值并不要求是唯一的,
唯一聚簇索引才是!

在一个有聚簇索引的列上是可以插入两个或多个相同值的,这些相同值在硬盘上的物理排序与聚簇索引的排序相同,仅此而已。

1.5.2 唯一索引与主键

唯一索引是在表上一个或者多个字段组合建立的索引,这个(或这几个)字段的值组合起来在表中不可以重复。一张表可以建立任意多个唯一索引,但一般只建立一个。

主键是一种特殊的唯一索引,区别在于,唯一索引列允许null值,而主键列不允许为null值。一张表最多建立一个主键,也可以不建立主键。

1.5.3 索引和主键的区别
  • 可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引。而主键只是其中的一种。主键属于索引的一种。
  • 主键用于强制表的实体完整性,聚集索引用来对数据行排序,方便查询用。
  • 一个表最多一个主键,一个表最多一个聚集索引
  • 一个表中可以有多个唯一索引,但是只能有一个主键
  • 主键列不允许空值,而唯一索引列允许空值。
2 索引数据结构

mysql主要用到B+树和hash两种索引。
memory用hash索引,innodb和mysam是b+树索引。

2.1 树型

二叉树->AVL树->红黑树->B-树->B+树

  • 二叉树会越查越高。尾部插入会退化为线性。

  • AVL树:带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡。和红黑树相比,它是严格的平衡二叉树。

    不适合做数据库索引。因为:
    (1) 当数据量大的时候,树的高度会比较高,数据量大的时候,查询会比较慢;
    (2) 每个节点只存储一个记录,可能导致一次查询有很多次磁盘IO
    (3) 旋转操作效率太低

  • 红黑树(弱平衡二叉平衡树):一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是red或black。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍。它是一种弱平衡二叉树

    红黑树问题:数据量越大,树高度越高,性能越低(查找效率低)。

    O次数多

  • B树:m叉搜索。叶子节点和非叶子节点都存储数据;中序遍历可以获取所有节点。
    ①叶节点具有相同的深度,叶节点指针为空;②所有索引元素不重复;③节点中数据索引从左到右递增

    缺点:
    (1)节点要存储数据和索引,一个内存页可存储数据还是少
    (2)范围查找需要多次IO

  • B+树(多路平衡查找树):①非叶子节点不存储data,只存储索引(冗余),可以存放更多索引;②叶子节点包含所有索引字段;③叶子节点用指针连接,提高区间访问性能;

    优点:
    (1). 只有叶子节点保存数据,可以存放更多索引,
    (2). 底层双向链表,方便范围查找。

    mysql对叶子节点的冗余索引是加载到内存中的(数据还是在磁盘中),最终做一次IO磁盘查找,效率很高。
    b+树一般1-3层就可以实现千万级别的数据查找

2.2 HASH

哈希桶里面的链表里,也放索引文件对应的磁盘文件地址。
算法时间复杂度是O(1),hash算法查找效率很高。但是只能查找一条。因为有 hash不支持范围查找——只好全表扫描(如>'Tom’文件的所有文件,无法过滤)、hash冲突为题。

select * from t where name=”shenjian”;


如果只有报表的等值查找,用hash效率可能比较高。但其实现实用的很少。因为实际是要范围查找,有很多有序需求。

不用hash

  • 内存上:索引需要把存储在磁盘上的数据都加载进内存,采用Hash索引遇到大数据量的数据时无法一次性加载进内存;B+树的高度低,非叶子节点不存储数据,允许数据分批加载
  • 业务上:B+树的叶子节点是有序的,可以在叶子节点上进行范围查找。
3 索引数据引擎和聚集索引、非聚集索引 3.1 myisam和innoDB

mysql现在基本用innoDB
myISAM索引文件和数据文件是分离的(非聚集索引——稀疏索引)

3.1.1 myisam

索引元素和数据元素分开存储

frm存储框架,MYI索引,MYD数据
mysam的叶子节点的data放的是索引所在行的磁盘文件地址,然后去查myd文件去定位改行数据的所有数据值(回表)。

3.1.2 innoDB

InnoDB索引实现(索引)
frm框架,ibd索引和数据都在这个文件里。

如果有主键就使用主键,没有就使用唯一键,没有唯一键就使用6字节的rowid。

和数据放在一起的是聚集索引,而为了避免数据冗余存储,其他的索引的叶子节点中存储的都是聚集索引的key值。因此:innodb中既有聚集索引也有非聚集索引。而myisam中只有非聚集索引。

数据和索引放在一个文件里。表数据文件本身按B+树组织的索引结构文件,来组织数据。
叶子节点除了索引,还放索引所在行的其他所有数据。(聚集索引——聚簇索引)
索引元素和数据元素一起存储

二级索引
innodb的普通索引(二级索引),根据索引b+树来定位到元素拿到主键,然后到主键索引树里定位具体记录所有元素(这也是回表查询),效率比主键查找效率。非聚集索引叶子节点存储的是主键值。

回表查询

先通过普通索引的值定位聚簇索引值,再通过聚簇索引的值定位行记录数据,需要扫描两次索引B+树,它的性能较扫一遍索引树更低。

3.2 QA

问题1:一定要建主键,建会比不建好很多。
B+树的元素可以从主键索引里来,没有建主键的话怎么维护数据?mysql会在表里找出一列可以做唯一索引的,用这列数据来组织所有数据,维护到B+树上来。

找不到唯一索引,就后台维护一个隐藏链(自增、唯一的),然后用这个隐藏链来维护b+树。
自家建一个主键,可以提高mysql的性能,减少mysql做维护工作。

问题2:整型?b+树会做大量的查找比对(折半查找、查找等),整型比大小快,字符串比大小慢。存储空间占的小。

问题3:自增?(见下):B+树适合范围查找,叶子节点尾部双向链表,是相邻节点的磁盘文件地址。而且从左到右依次递增。 双向指针提高区间访问性能。

如果先插8再插7(会做平衡):维护的不是自增。如果是自增的,永远在后面加元素。很少会导致插入元素后节点分裂(16KB放满),下层层元素还要往上提,上面节点顺序重新排列。效率会掉很多
树结构会分裂、旋转、平衡,效率不会高。

问题4:B+和B树本质区别:B树叶子节点没有双向指针;B树非叶子节点保存data。为什么用B+不用B?

B+树非叶子节点不存储data,只存储索引(冗余),可以放更多的索引。B+树空间利用率更高。
B+树的叶子节点包含所有索引字段。
B+树支持范围查找(多了双向指针),存储索引,B树会更高。在进行范围查找时,B树需要从根节点向下遍历,造成大量随机I/O。而B+树通过双向链表,查找更加便利并且只会产生固定I/O。

高度为3,B+树就可以放2000W个索引。B树的高度会比3大。决定树高度的本质是非叶子节点。非叶子节点可以分叉更多的叶子节点的话,可以存储更多树。

B+树可以达到千万级别的数量的查找,一个块可以存16KB,字数就是a=16*16,总共可以千万级别的数据量。

索引在id上建的比较多。

4 联合索引与覆盖索引 4.1 联合索引

代码:

CREATE INDEX 索引名 ON 表名(列名X, 列名Y, 列名Z);

其实这相当于建立了三个索引,分别是:

  • 单列索引(列X)
  • 复合索引(列X, 列Y)
  • 复合索引(列X,列Y,列Z)

联合索引:指的是对表中的多个列进行索引,联合索引也是一棵B+树,不同的是键值数量大于等于1。

select * from table 
where a=XX and b=XX (联合索引 (a,b))
4.2 覆盖索引

覆盖索引:一种特殊的联合索引,即你查询的字段所有数据都在索引上,不需要再进行一次回表查询,这样的索引即为覆盖索引。

当sql语句的所求查询字段(select列)和查询条件字段(where子句)全都包含在一个索引中(联合索引),可以直接使用索引查询而不需要回表。这就是覆盖索引。

1 A: select id from user_table where name= '张三'
2 B: select password from user_table where name= '张三'

A:因为 name索引树 的叶子结点上保存有 name和id的值 ,所以通过 name索引树 查找到id后,因此可以直接提供查询结果,不需要回表,也就是说,在这个查询里面,索引name 已经 “覆盖了” 我们的查询需求,我们称为 覆盖索引。
B: name索引树 上 找到 name=‘张三’ 对应的主键id, 通过回表在主键索引树上找到满足条件的数据

如果查询条件使用的是普通索引(或是联合索引的最左原则字段),查询结果是联合索引的字段或是主键,不用回表操作,直接返回结果,减少IO磁盘读写读取正行数据

select id,age from user where age = 10;

解说:https://www.cnblogs.com/s42-/p/13596212.html

4.3 mysql最左前缀优化原则

实际会推荐:联合索引,不要建太多单值索引。
当遇到范围查询(>、<、between、like)就会停止匹配。

主键联合索引:第一个字段相等,则按第二个字段排序。

这里只有第一个走了联合索引,其他因为没符合左前缀原则,因此没走联合索引。


左前缀原则底层原理:age, position不是第一个,在所有叶子节点里没有排好序。跳过了第一个索引,后面的索引中没有排好序,还是要全表扫描。第一个元素找到后,只要在这一个小块里定位查找,后面的不用再找了!

猴哥:只查一次能查出来的叫覆盖索引。
a=1,b>5,c=2

范围查找不可以走索引,只可以命中a的索引。b因为是范围,a>=2也不能走索引。

4.4 QA
  1. sql为:SELECt * FROM table WHERe a = 1 and b = 2 and c = 3; 如何创建索引?
    答案:(a,b,c)或者(c,b,a)或者(b,a,c)都可以,重点要的是将区分度高的字段放在前面,区分度低的字段放后面。

  2. sql为:SELECt * FROM table WHERe a > 1 and b = 2; 如何创建索引?
    答:对(b,a)建立索引。 最左匹配原则遇到范围查询就停止匹配。

  3. sql为:SELECt * FROMtableWHERe a > 1 and b = 2 and c > 3;
    答:(b,a)或者(b,c)都可以,要结合具体情况具体分析。

  4. SELECt * FROMtableWHERe a = 1 ORDER BY b;
    答:一看就是对(a,b)建索引,当a = 1的时候,b相对有序,可以避免再次排序!

SELECt * FROMtableWHERe a > 1 ORDER BY b;
答:对(a)建立索引,因为a的值是一个范围,这个范围内b值是无序的,没有必要对(a,b)建立索引。

  1. SELECt * FROMtableWHERe a IN (1,2,3) and b > 1;
    答:还是对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)!
5 索引应用细节

阿里规约

表记录很多,又没有很好地索引,表关联的时候可能会做上百万次的数据表扫描和运算。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/279924.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号