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

索引模型有三种常见、也比较简单的数据结构分别是哈希表、有序数组和搜索树。

哈希表

哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value。哈希的思路很简单,把值放在数组里,用一个哈希函数把 key 换算成一个确定的位置,然后把 value 放在数组的这个位置。

适用于只有等值查询的场景,比如 Memcached 及其他一些NoSQL 引擎。

有序数组

有序数组在等值查询和范围查询场景中的性能就都非常优秀。

这里我们假设身份证号没有重复,这个数组就是按照身份证号递增的顺序保存的。这时候如果你要查 ID_card_n2 对应的名字,用二分法就可以快速得到,这个时间复杂度是O(log(N))。

如果仅仅看查询效率,有序数组就是最好的数据结构了。但是,在需要更新数据的时候就麻烦了,你往中间插入一个记录就必须得挪动后面所有的记录,成本太高。所以,有序数组索引只适用于静态存储引擎,比如你要保存的是 2017 年某个城市的所有人口信息,这类不会再修改的数据。

二叉搜索树

二叉搜索树的时间复杂度是 O(log(N))。树可以有二叉,也可以有多叉。多叉树就是每个节点有多个儿子,儿子之间的大小保证从左到右递增。二叉树是搜索效率最高的,但是实际上大多数的数据库存储却并不使用二叉树。其原因是,索引不止存在内存中,还要写到磁盘上。

为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该使用二叉树,而是要使用“N 叉”树。这里,“N 叉”树中的“N”取决于数据块的大小。

InnoDB 的索引模型

在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。

每一个索引在 InnoDB 里面对应一棵 B+ 树。

假设,我们有一个主键列为 ID 的表,表中有字段 k,并且在 k 上有索引。

假如建表语句如下:

mysql> create table T(
id int primary key,
k int not null,
name varchar(),
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 索引树搜索一次。这个过程称为回表。

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

为什么主键需要自增呢?

这样每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂,性能高得多。

而且主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。

所以,从性能和存储空间方面考量,自增主键往往是更合理的选择。

最左前缀原则

由于覆盖索引可以减少树的搜索次数,显著提升查询性能,减少回表,所以使用覆盖索引是一个常用的性能优化手段。

在建立联合索引的时候,如何安排索引内的字段顺序?

第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。

,如果既有联合查询,又有基于 a、b 各自的查询呢?查询条件里面只有 b 的语句,是无法使用 (a,b) 这个联合索引的,这时候你不得不维护另外一个索引,也就是说你需要同时维护 (a,b)、(b) 这两个索引。

这时候,我们要考虑的原则就是空间了。比如上面这个市民表的情况,name 字段是比 age 字段大的 ,那我就建议你创建一个(name,age) 的联合索引和一个 (age) 的单字段索引。

索引下推

我们还是以市民表的联合索引(name, age)为例。如果现在有一个需求:检索出表中“名字第一个字是张,而且年龄是 10 岁的所有男孩”。那么,SQL 语句是这么写的:
mysql> select * from tuser where name like '张 %' and age= and ismale=;

MySQL 5.6 之前,只能从 ID3 开始一个个回表。到主键索引上找出数据行,再对比字段值。

而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数,如下图所示:

深入浅出Mysql索引的更多相关文章

  1. 深入浅出Mysql索引优化专题分享|面试怪圈

    文章纲要 该文章结合18张手绘图例,21个SQL经典案例.近10000字,将Mysql索引优化经验予以总结,你可以根据纲要来决定是否继续阅读,完成这篇文章大概需要25-30分钟,相信你的坚持是不负时光 ...

  2. 深入浅出Mysql索引的那些事儿

    文章来源:公众号:猿人谷 一.索引的作用 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优 ...

  3. 深入浅出分析MySQL索引设计背后的数据结构

    在我们公司的DB规范中,明确规定: 1.建表语句必须明确指定主键 2.无特殊情况,主键必须单调递增 对于这项规定,很多研发小伙伴不理解.本文就来深入简出地分析MySQL索引设计背后的数据结构和算法,从 ...

  4. MySQL索引原理及慢查询优化-来自美团网的技术blog(写的深入浅出)

    MySQL索引原理及慢查询优化 转:http://tech.meituan.com/mysql-index.html MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首 ...

  5. 《深入浅出MySQL》之数据类型

    MySQL提供了多种数据类型,主要包括数值型.字符串型和日期时间类型.本次博客就来谈谈MySQL中常用的数据类型吧(版本:mysql-5.7.19)! 数值类型 MySQL支持所有标准SQL中数值类型 ...

  6. MySQL——索引优化实战

    上篇文章中介绍了索引的基本内容,这篇文章我们继续介绍索引优化实战.在介绍索引优化实战之前,首先要介绍两个与索引相关的重要概念,这两个概念对于索引优化至关重要. 本篇文章用于测试的user表结构: 索引 ...

  7. MySQL——索引基础

    本篇文章,我们将从索引基础开始,介绍什么是索引以及索引的几种类型,然后学习如何创建索引以及索引设计的基本原则. 本篇文章中用于测试索引创建的user表的结构如下: 什么是索引 索引(在 MySQL 中 ...

  8. 如何向女朋友介绍MySQL索引

    目录 一.前言 二.正文 三.索引的类型 四.动态查找树 五.B-Tree 1.B-Tree特征 2.B-Tree的查找(select) 3.B-Tree的插入(insert) 4.B-Tree的删除 ...

  9. mysql 索引十连问| 剑指 offer - mysql

    以下是结合网上及此前面试时遇到的一些关于mysql索引的面试题. 若对mysql索引不太了解可先翻阅相关文章 大白话 mysql 之深入浅出索引原理 - 上 大白话 mysql 之深入浅出索引原理 - ...

随机推荐

  1. Linux基础-----------nginx安装和nginx web、nginx反向代理、nfs 服务

    作业一:nginx服务1)二进制安装nginx包 yum install epel-release -y 先安装epel-release 再查看yum源中已经安装上了epel相关文件 中间省去了一些安 ...

  2. 【线段树】【CF19D】 Points

    传送门 Description 在一个笛卡尔坐标系中,定义三种操作: \(add(x,y)\),将点\((x,y)\)标记在坐标系上 \(find(x,y)\),查询点\((x,y)\)严格右上方中, ...

  3. mysql四-2:多表查询

    一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 准备表 #建表 create table department( id int, name varchar(20) ); create ta ...

  4. 流媒体协议之RTP详解20170921

    1.RTP介绍 实时传输协议RTP(Real-time Transport Protocol)是一个网络传输协议,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的,后在RFC35 ...

  5. 图像RGB格式与YUV格式互转

    // rgb2yuv.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #define Level 256 //直方图bin数 #define ...

  6. bootstrap 栅格calss

    container container-fluid row col-xs- col-sm- col-md- col-lg- col-md-offset- col-md-push- col-md-pul ...

  7. [DeeplearningAI笔记]卷积神经网络3.6-3.9交并比/非极大值抑制/Anchor boxes/YOLO算法

    4.3目标检测 觉得有用的话,欢迎一起讨论相互学习~Follow Me 3.6交并比intersection over union 交并比函数(loU)可以用来评价对象检测算法,可以被用来进一步改善对 ...

  8. java 关于值引用、地址引用的问题

    8种基本引用类型 四种整数类型(byte.short.int.long) 两种浮点数类型(float.double) 一种字符类型(char) 一种布尔类型(boolean) 以及如String, f ...

  9. [Luogu 1196] NOI2002 银河英雄传说

    [Luogu 1196] NOI2002 银河英雄传说 话说十六年前的 NOI 真简单... 我一开始还把题看错了- 题意:一群人,每个人各自成一队,每次命令让两队首位相接合成一队,每次询问问你某两个 ...

  10. 批量提取图片主要3个颜色匹配中文名字并写入到excel设置对应颜色的背景

    from gevent import monkey monkey.patch_all() import gevent from haishoku.haishoku import Haishoku im ...