一、 什么是索引

在关系数据库中,索引是一种单独的、物理的数对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。

索引图示

二、 为什么需要建立索引

当数据保存在磁盘类存储介质上时,它是作为数据块存放。这些数据块是被当做一个整体来访问的,这样是为了保证操作的原子性。磁盘数据块存储结构类似于链表存储结构,每个数据块包含数据部分,以及指向下一个数据块(节点)的指针,不要连续的数据块进行存储。

记录集只能在某一个关键字段上排序,因此如果想要在一个无序字段上搜索数据,就要执行一个线性搜索的过程,平均需要访问N/2个数据块,N表示数据占用的数据块数目。

如果这个字段是一个非主键字段(也就是说,不包含唯一访问入口),那么需要访问整个数据存储的数据块。

而如果数据是有序的,则可以使用二分法查找,这样只需要访问log2(N)的数据块,这也就是我们为什么有序的字段查询速度更快的原因。

三、索引类型

Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。

FULLTEXT

即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE INDEX创建FULLTEXT索引,要比先为一张表建立FULLTEXT然后再将数据写入的速度快很多。

全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%”这类针对文本的模糊查询效率较低的问题。在没有全文索引之前,这样一个查询语句是要进行遍历数据表操作的。可见,在数据量较大时是极其耗时的,如果没有异步IO处理,进程将被挟持,很浪费时间。

全文索引的使用方法并不复杂:

创建索引

ALTER TABLE table

ADD INDEX `FULLINDEX`

USING FULLTEXT(`cname1`[,cname2…]);

使用

SELECT * FROM table

WHERE MATCH(cname1[,cname2…]) AGAINST ('word' MODE );

其中, MODE为搜寻方式,主要有下面三种搜寻方式。

IN BOOLEAN MODE

布尔模式,允许word里含一些特殊字符用于标记一些具体的要求,如+表示一定要有,-表示一定没有,*表示通用匹配符,是不是想起了正则,类似吧;

IN NATURAL LANGUAGE MODE

自然语言模式,就是简单的单词匹配;

IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION

含表达式的自然语言模式,就是先用自然语言模式处理,对返回的结果,再进行表达式匹配。

对搜索引擎稍微有点了解的同学,肯定知道分词这个概念,FULLTEXT索引也是按照分词原理建立索引的。西文中,大部分为字母文字,分词可以很方便的按照空格进行分割。但很明显,中文不能按照这种方式进行分词。那又怎么办呢?这个向大家介绍一个Mysql的中文分词插件Mysqlcft,有了它,就可以对中文进行分词,想了解的同学请移步Mysqlcft,当然还有其他的分词插件可以使用。

HASH

Hash这个词,可以说,自打我们开始码的那一天起,就开始不停地见到和使用到了。其实,hash就是一种(key=>value)形式的键值对,如数学中的函数映射,允许多个key对应相同的value,但不允许一个key对应多个value。正是由于这个特性,hash很适合做索引,为某一列或几列建立hash索引,就会利用这一列或几列的值通过一定的算法计算出一个hash值,对应一行或几行数据(这里在概念上和函数映射有区别,不要混淆)。在java语言中,每个类都有自己的hashcode()方法,没有显示定义的都继承自object类,该方法使得每一个对象都是唯一的,在进行对象间equal比较,和序列化传输中起到了很重要的作用。

hash的生成方法有很多种,足可以保证hash码的唯一性,例如在MongoDB中,每一个document都有系统为其生成的唯一的objectID(包含时间戳,主机散列值,进程PID,和自增ID)也是一种hash的表现。

由于hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。那为什么还需要其他的树形索引呢?引用下园子里其他大神的文章:来自 14的路 的MySQL的btree索引和hash索引的区别

Hash 索引仅仅能满足”=”,”IN”和”<=>”查询,不能使用范围查询。

由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。

Hash 索引无法被用来避免数据的排序操作。

由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;

Hash 索引不能利用部分索引键查询。

对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。

Hash 索引在任何时候都不能避免表扫描。

前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。

Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。

对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。

当我们为某一列或某几列建立hash索引时(目前就只有MEMORY引擎显式地支持这种索引),会在硬盘上生成类似如下的文件:

hash值

存储地址

1db54bc745a1

77#45b5

4bca452157d4

76#4556,77#45cc…

hash值即为通过特定算法由指定列数据计算出来,磁盘地址即为所在数据行存储在硬盘上的地址(也有可能是其他存储地址,其实MEMORY会将hash表导入内存)。

这样,当我们进行WHERE age = 18 时,会将18通过相同的算法计算出一个hash值==>在hash表中找到对应的储存地址==>根据存储地址取得数据。

所以,每次查询时都要遍历hash表,直到找到对应的hash值,如(4),数据量大了之后,hash表也会变得庞大起来,性能下降,遍历耗时增加,如(5)。

BTREE

BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中。如二叉树一样,每次查询都是从树的入口root开始,依次遍历node,获取leaf。

BTREE在MyISAM里的形式和Innodb稍有不同

在 Innodb里,有两种形态:一是primary key形态,其leaf node里存放的是数据,而且不仅存放了索引键的数据,还存放了其他字段的数据。二是secondary index,其leaf node和普通的BTREE差不多,只是还存放了指向主键的信息.

而在MyISAM里,主键和其他的并没有太大区别。不过和Innodb不太一样的地方是在MyISAM里,leaf node里存放的不是主键的信息,而是指向数据文件里的对应数据行的信息。

RTREE

RTREE在mysql很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。

相对于BTREE,RTREE的优势在于范围查找.

各种索引的使用情况

对于BTREE这种Mysql默认的索引类型,具有普遍的适用性

由于FULLTEXT对中文支持不是很好,在没有插件的情况下,最好不要使用。其实,一些小的博客应用,只需要在数据采集时,为其建立关键字列表,通过关键字索引,也是一个不错的方法。

对于一些搜索引擎级别的应用来说,FULLTEXT同样不是一个好的处理方法,Mysql的全文索引建立的文件还是比较大的,而且效率不是很高,即便是使用了中文分词插件,对中文分词支持也只是一般。真要碰到这种问题,Apache的Lucene或许是你的选择。

正是因为hash表在处理较小数据量时具有无可比拟的素的优势,所以hash索引很适合做缓存(内存数据库)。如mysql数据库的内存版本Memsql,使用量很广泛的缓存工具Mencached,NoSql数据库redis等,都使用了hash索引这种形式。当然,不想学习这些东西的话Mysql的MEMORY引擎也是可以满足这种需求的。

至于RTREE,使用较少。

mysql里sql语句值得注意的地方

myisam里所有键的长度仅支持1000字节,innodb是767.

blob和text字段仅支持前缀索引.

使用!=以及<>不等于的时候,mysql不使用索引.

当在字段时候函数的时候,mysql无法使用索引;在join时条件字段类型不一致的时候,mysql无法使用索引;在组合索引里使用非第一个索引时也不使用索引.

在使用like的时候,以%开头,即”%***”的时候无法使用索引;在使用or的时候,要求or前后字段都有索引.

有时候mysql query optimizer会认为使用索引并不是最优计划,所以不使用索引。可以在sql语句里可以用use,force index,当然有时候使用也不会比不用快,所以需要忽略掉index方法是ignore index.

mysql索引工作原理btree_MySQL:索引工作原理相关推荐

  1. 一篇读懂聚集索引、非聚集索引、覆盖索引的工作原理!

    作者:PostTruth 「数据库」和「数据库索引」这两个东西是在服务器端开发领域应用最为广泛的两个概念,熟练使用数据库和数据库索引是开发人员在行业内生存的必备技能. 使用索引很简单,只要能写创建表的 ...

  2. 数据库索引优化原理,索引的工作机制

    我们通过一个简单的例子来开始教程,解释为什么我们需要数据库索引.假设我们有一个数据库表 Employee, 这个表有三个字段(列)分别是 Employee_Name.Employee_Age 和Emp ...

  3. MySQL索引背后的数据结构及算法原理【转】

    http://blog.codinglabs.org/articles/theory-of-mysql-index.html MySQL索引背后的数据结构及算法原理[转] 摘要 本文以MySQL数据库 ...

  4. 一上来,就问原理,问上亿(MySQL)大表的索引优化...

    你经历过地狱级的面试吗?血淋淋的教训告诉你 你好,x先生,欢迎来我们公司面试,不用太紧张,我们简单聊一个 好的,谢谢您 看了你的简历,之前对mysql数据库了解挺多的,我们先来聊聊数据库怎么样? 好的 ...

  5. MySQL索引背后的数据结构及算法原理--转

    MySQL索引背后的数据结构及算法原理 作者 张洋 | 发布于 2011-10-18 MySQL 索引 B树 优化 原文地址:http://blog.codinglabs.org/articles/t ...

  6. MySQL索引背后的数据结构及算法原理zz

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 也各不相同,因此MySQL数据库支持多种索引类型,如B ...

  7. 【转载】MySQL索引背后的数据结构及算法原理

    本文转载自http://blog.jobbole.com/24006/ 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储 ...

  8. MySQL索引背后的数据结构及算法原理----惊叹的深入

    原文出处: 张洋    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库 ...

  9. mysql 按时间累计计算_精通MySQL索引背后的数据结构及算法原理

    本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,mysql支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree ...

最新文章

  1. 用bash命令得到Windows一个目录下的所有文件并且把结果输入到一个文件
  2. 看大神如何使用vue导出pdf
  3. 【线性规划与网络流24题】孤岛营救问题 分层图
  4. 基于CkEditor实现.net在线开发之路(1)
  5. EndNote 20的同步功能如何使用?及新版下载
  6. 探测与响应是各企业机构在2017年的首要安全事务
  7. ElasticSearch 2 (27) - 信息聚合系列之故事开始
  8. 通过SVD求解单应矩阵
  9. go语言结构体作为函数参数,采用的是值传递
  10. win10系统:VMware无法在Windows运行该怎么办?
  11. python遍历数组冒泡排序_Python算法(一) 数组冒泡排序(难度等级:easy)
  12. 各种文件的mime类型
  13. 概率论与数理统计——常用结论
  14. 医院时钟系统,NTP子钟,网络子母钟系统,ntp子母钟,网络子母钟——为您的系统保驾护航
  15. 软件测试工程师面试题汇总
  16. python上下对齐_python-docx设置表格对齐方式
  17. 【ultraedit编辑器中怎么取消文件自动备份】
  18. Give root password for maintenace (or press Control-D to continue):解决方法
  19. 数据库中码、超码、主码、候选码
  20. c语言中英语部分,C语言部分函数(国外英语资料).doc

热门文章

  1. 华为q1设置虚拟服务器,快速设置手机解决 华为Q1系统解析_华为 路由Q1_网络设备无线网络和技术-中关村在线...
  2. Python 线上部署流程
  3. 天龙八部服务器端共享内存的设计(3/3)
  4. java转义空格_java中如何输出空格
  5. 一个简单、功能完整的WMS​仓库管理系统
  6. fisco bcos证书体系
  7. 如何实现C++和C的混合编程?
  8. 得帆信息徐翔轩:低代码市场成熟起来,大概需要三五年
  9. python猜拳游戏编程代码_用python实现“猜拳游戏
  10. C语言编程输出特殊图案