返回顶部
首页 > 资讯 > 数据库 >04.深入浅出索引(上)
  • 628
分享到

04.深入浅出索引(上)

04.深入浅出索引(上) 2020-03-05 00:03:22 628人浏览 猪猪侠
摘要

   简单来说,索引的出现就是为了提高数据查询效率,就像书的目录一样。 索引的常见模型 索引实现的方式有很多种,所以这里就引入了索引模型的概念,可以用于提高读写效率的数据结构很多,比较常见的数据结果有以下三种:哈希表、有序数组和搜索树。

   简单来说,索引的出现就是为了提高数据查询效率,就像书的目录一样。

索引的常见模型

索引实现的方式有很多种,所以这里就引入了索引模型的概念,可以用于提高读写效率的数据结构很多,比较常见的数据结果有以下三种:哈希表、有序数组和搜索树。

  • 哈希表是一种以键值存储数据的结构,我们只要输入待查找的值即key,就可以找到对应的值即Value。哈希的思路很简单,把值放到一个数据里,用一个哈希函数把Key换算成一个确定的位置,然后把value放在数组的这个位置上。不可避免的,多个key通过哈希函数的换算,会出现同一个值的情况,处理这种情况的方法是,拉出一个链表。所以哈希表这种结构适用于只有等值查询的场景。
  • 有序数据在等值查询和范围查询场景中的性能就都非常优秀,但是在需要更新数据的时候就麻烦了,你往中间插入一条记录,就必须行挪动后面所有的记录,成本太高。
  • 二叉搜索树:每个节点的左儿子小于父节点,父节点又小于右儿子,查询的时间复杂度为O(log(N)),数据库存储大多不使用二叉树,因为树高过高。一般使用N叉树。

InnoDB的索引模型

    在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表,又因为InnoDB使用了B+树索引模型,所以数据都是存储在B+树中。每一个索引在InnoDB里面对应一棵B+树。(为什么InnoDB选择B+树,因为B+树能够很好地配合磁盘的读写特性,减少单次查询的磁盘访问次数)

   假如,有一个主键列为ID的表,表中有字段k,并且k上有索引,这个表的创建语句为:

create table T ( id int primary key, k int not null, name varchar(16), index (k)) engine=InnoDB;

表中 R1~R5的(ID,k)值分别为(100,1)、(200,2)、(300,3)、(500,5)和(600,6) 两棵树的示意图如下。

根据叶子节点的类容,索引类型分为主键索引和非主键索引,主键索引的叶子节点存的是整行数据,在InnoDB里面,主键索引也被称为聚簇索引(clustered index)。非主键索引的叶子节点存的内容是主健的值。在InnoDB里面,非主键索引也被称为二级索引(secondary index)。

主键索引和普通索引的查询有什么区别

  • 如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索ID这棵B+树;
  • 如果语句是select * from T where k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID的值为500,再到ID索引树搜索一次这个过程称为回表。

也就是说,基于非主键索引的查询需要多扫描一棵索引树,因此,我们在应用中尽量使用主键查询。

索引维护

    B+树为了维护索引的有序性,在插入新值的时候需要做必要的维护。以上面图为例,如果插入新的行的ID=700,则只需要在R5的记录后面新插入一个新记录。如果新插入的ID值=400,就相对麻烦了,需要逻辑上挪动后面的数据,空出位置。更糟糕的情况是,如果R5所在的数据页已经满了,根据B+树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受到影响。

    除了性能外,页分裂操作还会影响数据页的利用率。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约50%。

    当然有分裂就有合并。当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并,合并过程可以认为是分裂过程的逆过程。

下面我们来讨论一个案例:

   你有可能在一些建表规范里面见到过类似的描述,要求建表语句里一定要有自增主键。当然事无绝对,我们来分析一下哪些场景下应该使用自增主键,而哪些场景下不应该。

自增主键是指自增列上定义的主键,在建表语句中一般这么定义:NOT NULL PRIMARY KEY AUTO_INCREMENT。插入新记录时可以不指定ID的值,系统会获取当前ID最大值+1做为下一条记录的ID值。也就是说,自增主键的插入数据模式正符合了我们前面提到的递增插入的场景,都不涉及到挪动其它记录,也不会触发叶子节点的页分裂。

而有业务逻辑的字段做主键,则往往不易保证有序插入,这样定数据成本相对较高。除了考虑性能外,我们可以从存储空间的角度来看,假高你的表中确实有一个唯一字段,比如字条类型的身份证号,那应该用身份证号做主键还是用自增主键呢?由于每个非主键索引的叶子节点上存的都是主键的值,如果用身份证号做主键的话,那么每个二级索引的叶子节点占用约20个字节,而如果用整行做主键,则只要4个字节,如果是长整行(bigint)则是8个字节。

显然,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。所以从性能和存储空间方面考虑,自增主键往往是更合适的选择。

那有没有什么场合适合用业务字段做主键的呢?还是有的,比如,有些业务场景需求是这样:

  • 只有一个索引
  • 该索引必须是唯一索引。

由于没有其它索引,所以也不用考虑其它索引的叶子节点大小的问题。直接将这个索引设置成主键,可以避免每次查询需要搜索两棵树。

如果表没有设置主键,InnoDB会默认给创建一个Rowid做主键。

为什么我们有时需要重建索引?

索引可能因为删除,或者页分裂等原因。导致数据页有空洞,重建索引的过程会创建一个新的索引,把数据按顺序插入,这样页面的利用率最高,也就是索引更紧凑、更省空间。

但我们重建主键索引后,普通索引就会失效,所以我们重重建索引一般用:alter table T engine=InnoDB,来代替。

您可能感兴趣的文档:

--结束END--

本文标题: 04.深入浅出索引(上)

本文链接: https://lsjlt.com/news/3056.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 04.深入浅出索引(上)
       简单来说,索引的出现就是为了提高数据查询效率,就像书的目录一样。 索引的常见模型 索引实现的方式有很多种,所以这里就引入了索引模型的概念,可以用于提高读写效率的数据结构很多,比较常见的数据结果有以下三种:哈希表、有序数组和搜索树。...
    99+
    2020-03-05
    04.深入浅出索引(上)
  • 05.深入浅出索引(下)
         在下面这个表T中,如果我们执行select * from T where k between 3 and 5,需要执行几次树的搜索操作,会扫描多少行? mysql> create table T ( id i...
    99+
    2018-05-04
    05.深入浅出索引(下)
  • C++深入浅出探索模板
    目录非类型模板参数模板特化函数模板特化类模板特化全特化偏特化模板分离编译模板的分离编译解决方法总结非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参:出现在模板参数列表中,...
    99+
    2024-04-02
  • 深入浅出MongoDB
                              ...
    99+
    2024-04-02
  • 深入浅出探索Java分布式锁原理
    目录什么是分布式锁?它能干什么?分布式锁实现方案基于数据库的分布式锁实现方案实现原理方案分析基于Redis的分布式锁实现方案基于sentnx命令的实现原理方案分析基于Redisson...
    99+
    2024-04-02
  • 深入浅出MappedByteBuffer(推荐)
    目录1.内存管理2.MappedByteBuffer的深度剖析2.1 map过程2.2 get过程3.性能分析4.总结java io操作中通常采用BufferedReader,Buf...
    99+
    2022-12-10
    深入浅出MappedByteBuffer MappedByteBuffer
  • 深入浅出JS的Object.defineProperty()
    目录前言对象的定义与赋值Object.defineProperty()语法说明属性的特性以及内部属性属性描述符数据描述符 --特有的两个属性(value,writable)存取描述符...
    99+
    2024-04-02
  • C++深入浅出探索数据结构的原理
    目录一、前言二、C++的数据结构三、定义结构四、访问结构成员五、结构作为函数参数六、指向结构的指针一、前言 因为C++的数据结构很多,很复杂,一篇文章根本讲不到所有的数据结构。即使写...
    99+
    2024-04-02
  • redis深入浅出分布式锁实现上篇
    目录问题描述解决方案编写代码优化之UUID防误删问题描述 随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原...
    99+
    2024-04-02
  • 深入浅析Mysql联合索引最左匹配原则
    前言 之前在网上看到过很多关于mysql联合索引最左前缀匹配的文章,自以为就了解了其原理,最近面试时和面试官交流,发现遗漏了些东西,这里自己整理一下这方面的内容。 最左前缀匹配原则 在mysql建立联合...
    99+
    2024-04-02
  • MySQL索引优化深入
    创建 test 测试表 CREATE TABLE `test` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `c1` varchar(10) DEFAULT NULL,  `c2`...
    99+
    2016-11-27
    MySQL索引优化深入
  • 深入理解MySQL索引
    前言 当提到MySQL数据库的时候,我们的脑海里会想起几个关键字:索引、事务、数据库锁等等,索引是MySQL的灵魂,是平时进行查询时的利器,也是面试中的重中之重。 可能你了解索引的底层是b+树,会加快查询,也会在表中建立索引,但这是远远不够...
    99+
    2017-02-27
    深入理解MySQL索引
  • 深入了解mysql索引
    1、索引原理 索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL不得不首先以第一条记录开始,然后读完整个表直到它找出相关的行。表越大,花费时间越多。对于一个有序字段,可以运用二分查找(Binary Se...
    99+
    2022-05-14
    MySQL 索引
  • PostgreSQL VACUUM 之深入浅出 (二)
    AUTOVACUUM AUTOVACUUM 简介 PostgreSQL 提供了 AUTOVACUUM 的机制。 autovacuum 不仅会自动进行 VACUUM,也会自动进行 ANALYZE,以分析统计信息用于执行计划。 在 postg...
    99+
    2021-08-13
    PostgreSQL VACUUM 之深入浅出 (二)
  • PostgreSQL VACUUM 之深入浅出 (三)
    VACUUM 相关参数 对 VACUUM 有了一定的了解之后,下面系统介绍下 VACUUM 相关参数。 VACUUM 相关参数主要分为三大类。 第一类 与资源相关参数 #----------------------------- # RE...
    99+
    2020-02-23
    PostgreSQL VACUUM 之深入浅出 (三)
  • PostgreSQL VACUUM 之深入浅出 (一)
    前言 VACUUM 是 PostgreSQL MVCC (Multiversion concurrency control) 实现的核心机制之一,是 PostgreSQL 正常运行的重要保证。本文将通过实例演示 PostgreSQL 为...
    99+
    2018-06-06
    PostgreSQL VACUUM 之深入浅出 (一)
  • PostgreSQL VACUUM 之深入浅出 (五)
    AUTOVACUUM to prevent wraparound autovacuum_freeze_max_age 是 AUTOVACUUM 最不常用的参数,也基本不需要优化,但却是 AUTOVACUUM 最重要的一个参数,因为它与 w...
    99+
    2019-06-12
    PostgreSQL VACUUM 之深入浅出 (五)
  • PostgreSQL VACUUM 之深入浅出 (四)
    VACUUM 参数优化 上面已经介绍过了以下设置表级 AUTOVACUUM 相关参数和 autovacuum_max_workers: ALTER TABLE pgbench_accounts SET (autovacuum_vacuum...
    99+
    2019-07-25
    PostgreSQL VACUUM 之深入浅出 (四)
  • JavaScript深入浅出__proto__和prototype
    目录构造函数和实例prototypeconstructor原型对象的原型原型链扩展知识总结首先我们先记住几个知识点: 每个函数都有一个prototype属性每个对象都有一个__pro...
    99+
    2024-04-02
  • 深入浅出Golang中的sync.Pool
    目录一、原理分析1.1 结构依赖关系图1.2 用图让代码说话1.3 Put过程分析二、学习收获2.1 如何自己实现一个无锁队列学习到的内容: 1.一个64位的int类型值,充分利用高...
    99+
    2023-03-13
    Golang sync.Pool原理 Golang sync.Pool使用 Golang sync.Pool
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作