码迷,mamicode.com
首页 > 数据库 > 详细

mysql-索引

时间:2018-04-01 13:07:57      阅读:331      评论:0      收藏:0      [点我收藏+]

标签:全表扫描   相对   组合   分配   依次   strong   定位   second   黑板   

索引概述

也没什么概述的(⊙﹏⊙)b,用索引就是为了加快查询速度,降低查询所消耗的资源。下面进入正题了,敲黑板!!!

索引类型

MySQL提供多种索引类型供

普通索引

这是最基本的索引类型,而且它没有唯一性之类的限制。

唯一性索引

它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。

主键索引

主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。

全文索引

MySQL从3.23.23版开始支持全文索引和全文检索。在 MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。

符合索引

比如有一条语句是这样的:select * from users where area=’beijing’ and age=22;

如果我们是在area和age上分别创建单个索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在area、age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age, salary)的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。

如何正确使用索引

  1. 索引不会包含有NULL值的列

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

  1. 使用短索引
  • 索引的长度

在为CHAR和VARCHAR类型的数据列定义索引时,可以把索引的长度限制为一个给定的字符个数(这个数字必须小于这个字段所允许的最大字符个数)。这 么做的好处是可以生成一个尺寸比较小、检索速度却比较快的索引文件。在绝大多数应用里,数据库中的字符串数据大都以各种各样的名字为主,把索引的长度设置 为10~15个字符已经足以把搜索范围缩小到很少的几条数据记录了。
在为BLOB和TEXT类型的数据列创建索引时,必须对索引的长度做出限制;MySQL所允许的最大索引长度是255个字符。

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

创建: alter table aid_info add index aid(aid(4));

  1. 索引列排序

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

  1. like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

  1. 不要在列上进行运算
  2. 不使用NOT IN和< >操作

索引缺点

1、索引要占用磁盘空间。通常情况下,这个问题不是很突出。但是,如果你创建每一种可能列组合的索引,索引文件体积的增长速度将远远超过数据文件。如果你有一个很大的表,索引文件的大小可能达到操作系统允许的最大文件限制。

2、对于需要写入数据的操作,比如DELETE、UPDATE以及INSERT操作,索引会降低它们的速度。这是因为MySQL不仅要把改动数据写入数据文件,而且它还要把这些改动写入索引文件。

索引原理

说到索引的原理必须先理解一种数据结构(b+tree),主流的数据库都是使用该结构作为数据表默认的索引数据结构。

B+tree

B-tree,平衡多路查找树(B-tree就是B树,网上好多人都理解为两个不同的,--!!),B是balance,一般用于数据库的索引。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。而B+tree是B-tree的一个变种,MySQL就普遍使用B+tree实现其索引结构。

B-Tree结构图如下:
技术分享图片

可以看到每个节点中不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点(即一个页)能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查询时的磁盘I/O次数,进而影响查询效率。

B+Tree结构图如下:

技术分享图片

1、所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

2、所有叶子节点之间都有一个链指针。

3、数据记录都存放在叶子节点中。

4、在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。这是为了方便相邻叶子结点之间的访问,不必每次都从根结点开始访问。因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

例如:

select field_name from table where field_name > 24 and field_name < 31.

它的搜索路径是先从根结点索引到25,紧接着根据指向下一个叶子结点的指针可以迅速找到30。针对这种连续数据块的搜索,这种数据结构是正是其优势所在。

为什么使这种结构

一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。

为了减少查找过程中磁盘I/O的存取次数,磁盘按需读取,要求每次都会预读的长度一般为页的整数倍。而且数据库系统将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。并把B-tree中的m值设的非常大,就会让树的高度降低,有利于一次完全载入。

聚集索引和非聚集索引

说完了B+tree数据结构,在说下聚集索引和非聚集索引,其实在数据库中的B+Tree索引可以分为聚集索引(clustered index)和非聚集索引也叫辅助索引(secondary index)

聚集索引
简单来说,它就是索引和数据在一个文件,因为一个表只能有一个主键,所以一个表只能有一个「聚集索引」,主键的作用就是把「表」的数据格式转换成「索引(平衡树)」的格式放置。(但是主键可不一定是聚集索引!!,下面会说如果没有主键会以哪种规则建立聚集索引)

结构如下:
技术分享图片

假如我们执行一个SQL语句:
select * from table where id = 1256;
首先根据索引定位到1256这个值所在的叶结点,然后再通过叶结点取到id等于1256的数据行。 这里不讲解平衡树的运行细节, 但是从上图能看出,树一共有三层, 从根节点至叶节点只需要经过三次查找就能得到结果。如下图
技术分享图片

然后说下mysql
对于Innodb,主键毫无疑问是一个聚集索引。但是当一个表没有主键,或者没有一个索引,Innodb规则如下:
1、如果一个主键被定义了,那么这个主键就是作为聚集索引
2、如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引
3、如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。

非聚集索引
索引和数据分别放到两个文件,索引树结构中各节点的值来自于表中的索引字段值, 假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。

每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。
结构如下:
技术分享图片

非聚集索引和聚集索引的区别在于, 通过聚集索引可以查到需要查找的数据, 而通过非聚集索引可以查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据,如下图
技术分享图片

不管以任何方式查询表, 最终都会利用主键通过聚集索引来定位到数据, 聚集索引(主键不一定是聚集索引)是通往真实数据所在的唯一路径。
然而, 有一种例外可以不使用聚集索引就能查询出所需要的数据, 这种非主流的方法 称之为「覆盖索引」查询, 也就是平时所说的复合索引或者多字段索引查询。 文章上面的内容已经指出, 当为字段建立索引以后, 字段中的内容会被同步到索引之中, 如果为一个索引指定两个字段, 那么这个两个字段的内容都会被同步至索引之中。

如下图:
技术分享图片

mysql-索引

标签:全表扫描   相对   组合   分配   依次   strong   定位   second   黑板   

原文地址:https://www.cnblogs.com/xckxue/p/8686040.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!