数据库索引 订阅
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。索引的一个主要目的就是加快检索表中数据,亦即能协助信息搜索者尽快的找到符合限制条件的记录ID的辅助数据结构。 展开全文
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。索引的一个主要目的就是加快检索表中数据,亦即能协助信息搜索者尽快的找到符合限制条件的记录ID的辅助数据结构。
信息
外文名
index
详    述
提高系统的性能
分    类
聚簇索引 非聚簇索引
中文名
数据库索引
目    的
加快对表中记录的查找或排序
优    点
迅速
数据库索引简介
索引是对数据库表中一个或多个列(例如,employee 表的姓名 (name) 列)的值进行排序的结构。例如这样一个查询:select * from table1 where id=10000。如果没有索引,必须遍历整个表,直到ID等于10000的这一行被找到为止;有了索引之后(必须是在ID这一列上建立的索引),即可在索引中查找。由于索引是经过某种算法优化过的,因而查找次数要少的多。可见,索引是用来定位的。从数据搜索实现的角度来看,索引也是另外一类文件/记录,它包含着可以指示出相关数据记录的各种记录。其中,每一索引都有一个相对应的搜索码,字符段的任意一个子集都能够形成一个搜索码。这样,索引就相当于所有数据目录项的一个集合,它能为既定的搜索码值的所有数据目录项提供定位所需的各种有效支持 [1]  。
收起全文
精华内容
下载资源
问答
  • 数据库索引设计与优化》提供了一种简单、高效、通用的关系型数据库索引设计方法。作者通过系统的讲解及大量的案例清晰地阐释了关系型数据库的访问路径选择原理,以及表和索引的扫描方式,详尽地讲解了如何快速地...
  • MySQL数据库索引优化

    2018-04-17 21:13:20
    介绍BTree索引和Hash索引,详细介绍索引的优化策略等等 1.Btree索引和Hash索引 2.安装演示数据库 3.索引优化策略上 4.索引优化策略中 5.索引优化策略下
  • 盖国强、姜承尧、金官丁、叶金荣、童家旺一众国内数据库界巨腕争相作序|支付宝、网易、云和恩墨众DB掌门连袂推荐的造是什么书吗
  • 数据库索引重建及修复语句
  • 高清完整版 数据库索引设计与优化 高清完整版 数据库索引设计与优化
  • 数据库索引

    万次阅读 多人点赞 2018-11-11 09:27:25
    数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询,更新数据库中表的数据.索引的实现通常使用B树和变种的B+树(mysql常用的索引就是B+树) 除了数据之外,数据库系统还维护为满足特定查找算法的数据...

    引言

    说白了,数据库的索引问题就是查找问题

    数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询,更新数据库中表的数据.索引的实现通常使用B树和变种的B+树(mysql常用的索引就是B+树)

    除了数据之外,数据库系统还维护为满足特定查找算法的数据结构,这些数据结构以某种方式引用数据.这种数据结构就是索引

    创建索引的好处

    ①通过创建索引,可以在查询的过程中,提高系统的性能

    ②通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性

    ③在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的时间

    创建索引的坏处

    ①创建索引和维护索引要耗费时间,而且时间随着数据量的增加而增大

    ②索引需要占用物理空间,如果要建立聚簇索引,所需要的空间会更大

    ③在对表中的数据进行增加删除和修改时需要耗费较多的时间,因为索引也要动态地维护

    应该在哪些列上创建索引呢

    ①经常需要搜索的列上

    ②作为主键的列上

    ③经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度

    ④经常需要根据范围进行搜索的列上

    ⑤经常需要排序的列上

    ⑥经常使用在where子句上面的列上

    不应该在哪些列上创建索引

    ①查询中很少用到的列

    ②对于那些具有很少数据值的列.比如人事表的性别列,bit数据类型的列

    ③对于那些定义为text,image的列.因为这些列的数据量相当大

    ④当对修改性能的要求远远大于搜索性能时.因为当增加索引时,会提高搜索性能,但是会降低修改性能

    索引的分类和使用

    按物理存储角度分:

    聚集索引

    表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余连续性的记录在物理上一样连续存放.聚集索引的缺点就是修改慢,因为为了使表记录和索引的排列顺序一致,在插入记录的时候,会对数据页重新排序

    非聚集索引

    表记录和索引的排列顺序不一定一致,两种索引都采用B+树的结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表记录的指针.非聚集索引层次多,不会造成数据重排

    按逻辑角度分

    2)普通索引,最基本的索引,它没有任何的限制

    4)复合索引(又叫做多列索引,联合索引):多个字段上建立的索引,提高复合条件查询的速度

    创建联合索引:create index idx_name_age on student(name,age);

    查看索引:show index from student;

    数据库索引在什么情况下失效

    (1)条件中用or(这就是为什么少用or的原因)

    (2)

    对于多列(复合、联合)索引,不是使用的第一部分,则不会使用索引。(最左匹配原则或者叫做最左前缀原则)

    比如:Index_SoftWareDetail索引包含(a,b,c) 三列,但是查询条件里面,没有a,b 列,只有c 列,那么 Index_SoftWareDetail索引也不起作用

    例如:bc   c   acb bac 都是不行的

    (3)like的模糊查询以%开头,索引失效

    (4)如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不会使用索引

    (5)如果MySQL预计使用全表扫描要比使用索引快,则不使用索引

    (6)判断索引列是否不等于某个值时。‘!=’操作符。比如:select * from SoftWareDetailInfo where SoftUseLine != 0

    (7)

    对索引列进行运算。这里运算包括+-*/等运算。也包括使用函数。比如:

    select * from SoftWareDetailInfo where SoftUseLine +0= 0

    此时索引不起作用。

    select * from SoftWareDetailInfo where count(SoftUseLine) = 0

    此时索引也不起作用。

    也就是说如果不是直接判断索引字段列,而是判断运算或其它函数处理后的索引列索引均不起作用。

    (8)索引字段进行判空查询时。也就是对索引字段判断是否为NULL时。语句为is null 或is not null。

      比如:select * from SoftWareDetailInfo where CreateTime is null 此时就不检索time字段上的索引表了。也就是索引在这条语句执行时失效了。

      接着再执行

    select * from SoftWareDetailInfo where CreateTime = '2015-04-11 00:00:00' 此时就会检索索引表了。索引又起作用了。

    (9)范围列可以用到索引(联合索引必须是最左前缀),但是范围列后面的列无法用到索引

    索引的优化

    ①尽量不要使用左模糊和全模糊,如果需要可以使用搜索引擎来解决

    ②union,in和or都可以命中索引,建议使用in

    ③负向条件查询不能使用索引,可以优化为in查询

    负向条件查询有:!=  <>  not in  not like等等

    例如:select * from user where status!=1 and status!=2

    优化为:select * from user where status in (0,3,4);

    ④合理使用联合索引的最左前缀原则

    如果在(a,b,c)三个字段上建立联合索引,那么它能够加快 a | (a,b) | (a,b,c) 三组查询速度。

    比如说把(username,password)建立了联合索引,因为业务上几乎没有password的单条件查询,而有很多username的单条件查询需求,所以应该建立(username,password)的联合索引,而不要建立(password,username)的联合索引

    注意:(1)建立联合索引的时候,要把查询频率较高的列放在最左边

    (2)如果建立了(a,b)索引,就不必再独立建立a索引。同理如果建立了(a,b,c)联合索引,就不必再独立建立a,(a,b)索引

    (3)存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如     where a>? and b=?,那么即使 a 的区分度更高,也必须把 b 放在索引的最前列。

    (4)最左前缀原则,并不是要求where后的顺序和联合索引的一致。下面的 SQL 语句也可以命中 (login_name, passwd) 这个联合索引。

    • selectuid, login_time from user where passwd=? andlogin_name=?

    但还是建议 where 后的顺序和联合索引一致,养成好习惯。

    ⑤把计算放到业务层而不是数据库层。(因为对索引列进行运算,不能命中索引)

    ⑥表数据比较少、更新十分频繁、数据区分度不高的字段上不宜建立索引。

    一般区分度在80%以上的时候就可以建立索引,区分度可以使用 count(distinct(列名))/count(*) 来计算。

    ⑦强制类型转换会全表扫描

    例如:如果phone字段是varchar类型,则下面的sql不能命中索引

    select * from user where phone = 18838003017

    可以优化为:select * from user where phone = ‘18838003017’

    ⑧利用覆盖索引进行查询操作,避免回表

    select uid,login_time from user where username=? and password=?

    如果建立了(username,password,login_time)的联合索引,由于login_time已经建立在索引中了,被查询的username和password就不用去row上获取数据了,从而加速查询

    ⑨在order by和group by中要注意索引的有序性

    如果order by是组合索引的一部分,应该将该字段放在组合索引的最后

    例如:where a=? and b=? order by c ->可以建立联合索引(a,b,c)

    如果索引中有范围查找,则索引的有序性无法利用

    例如:where a>10 order by b ->索引(a,b)无法排序

    ⑩建立索引的列,不许为null

    单列索引不存 null 值,复合索引不存全为 null 的值,如果列允许为 null,可能会得到“不符合预期”的结果集,所以,请使用 not null 约束以及默认值。

    sql语句的优化

    ①能用到索引尽量用到索引.对索引的优化实际上就是sql语句的调优

    ②任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

    ③尽量使用where,而不要使用having

    ④尽量使用多表查询,不要使用子查询

    ⑤where后的and.or左右执行顺序是从右至左

    运算符为and时--尽量把为假的放在右边

    运算符为or时--尽量把为真的放在右边

     

     

    展开全文
  • 数据库索引设计与优化》提供了一种简单、高效、通用的关系型数据库索引设计方法。作者通过系统的讲解及大量的案例清晰地阐释了关系型数据库的访问路径选择原理,以及表和索引的扫描方式,详尽地讲解了如何快速地...
  • SQL修复简单数据库索引错误,SQL修复简单数据库索引错误
  • Oracle与MySQL数据库索引设计与优化 PDF 扫描版 有目录
  • 查看mySQL数据库索引

    2014-04-11 11:41:23
    mySQL索引查看 select * from information_schema.statistics where table_schema='数据库名称' and table_name = '表名称'
  • SQL Server 数据库索引整理 重建 工具 针对SQL Server数据库(2000,2005,2008,2012),对指定的数据库进行索引的重建整理,从而提前数据库的查询效率。 此工具用C#编译,环境为Net FrameWork3.5 此工具是自动进行...
  • 数据库索引和分类

    2020-12-14 16:19:04
    什么是数据库索引? 我们再平时的开发中免不了用到数据库的索引,接下来就简单说一下数据库索引数据库索引用来干什么? 数据库索引就是为了提高数据的查询速率。 数据库索引有哪些? 聚集索引:在数据库中,所有...
  • 1. 什么是索引索引就像是书的目录,是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引中包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(BTree)中,使SQL可以快速有效地...

    Mysql优化汇总系列:https://blog.csdn.net/qq_32534441/article/details/86523894
    Mysql优化之三:数据库索引原理及优化:https://blog.csdn.net/qq_32534441/article/details/86493753
    Mysql优化系列:https://blog.csdn.net/qq_32534441/article/category/8610043

    1. 什么是索引:

    索引就像是书的目录,是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引中包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(BTree)中,使SQL可以快速有效地查找与键值关联的行。

    2. 索引的原理:

    索引的原理大致概括为以空间换时间,数据库在未添加索引的时候进行查询默认的是进行全量搜索,也就是进行全局扫描,有多少条数据就要进行多少次查询,然后找到相匹配的数据就把他放到结果集中,直到全表扫描完。而建立索引之后,会将建立索引的KEY值放在一个n叉树上(BTree)。因为B树的特点就是适合在磁盘等直接存储设备上组织动态查找表,每次以索引进行条件查询时,会去树上根据key值直接进行搜索,次数约为log总条数,底数为页面存储数,例如一个100万数据的表,页面存储数为100,那么有索引的查询次数为3次log1000000100,但是全量搜索为100万次搜索,这种方式类似于二分法,但是这个是n分法。



    3.为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能。

    第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。 
    第二,可以大大加快 数据的检索速度,这也是创建索引的最主要的原因。 
    第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。 
    第四,在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。 
    第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。 


    也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点,但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面。 

    第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 
    第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。 
    第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 


    索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引,例如: 

    在经常需要搜索的列上可以加快搜索的速度; 
    在作为主键的列上强制该列的唯一性和组织表中数据的排列结构; 
    在经常用在连接的列上 些列主要是一些外键,可以加快连接的速度; 
    在经常需要根据范围进行搜索的列上创建索引因为索引已经排序,其指定的范围是连续的; 
    在经常需要排序的列上创 建索引因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间; 
    在经常使用在WHERE子句中的列上面创建索引加快条件的判断速度。 


    同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点: 

    第一,对于那些在查询中很少使用或者参考的列不应该创建索引这是因 为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。 
    第二,对于那 些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。 
    第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。 
    第四,当修改性能远远大于检索性能时,不应该创建索 引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因 此,当修改性能远远大于检索性能时,不应该创建索引。 

    4.创建索引的方法和索引的特征 
    创建索引的方法 
    创 建索引有多种方法,这些方法包括直接创建索引的方法和间接创建索引的方法。直接创建索引,例如使用CREATE INDEX语句或者使用创建索引向导,间接创建索引,例如在表中定义主键约束或者唯一性键约束时,同时也创建了索引。虽然,这两种方法都可以创建索引,但 是,它们创建索引的具体内容是有区别的。 

    直接创建索引:
    使用CREATE INDEX语句或者使用创建索引向导来创建索引,这是最基本的索引创建方式,并且这种方法最具有柔性,可以定制创建出符合自己需要的索引。在使用这种方式 创建索引时,可以使用许多选项,例如指定数据页的充满度、进行排序、整理统计信息等,这样可以优化索引。使用这种方法,可以指定索引的类型、唯一性和复合 性,也就是说,既可以创建聚簇索引,也可以创建非聚簇索引,既可以在一个列上创建索引,也可以在两个或者两个以上的列上创建索引。 
    间接创建索引:
    过定义主键约束或者唯一性键约束,也可以间接创建索引。主键约束是一种保持数据完整性的逻辑,它限制表中的记录有相同的主键记录。在创建主键约束时,系统自动创建了一个唯一性的聚簇索引。虽然,在逻辑上,主键约束是一种重要的结构,但是,在物理结构上,与主键约束相对应的结构是唯一性的聚簇索引。换句话说,在物理实现上,不存在主键约束,而只存在唯一性的聚簇索引。同样,在创建唯一性键约束时,也同时创建了索引,这种索引则是唯一性的非聚簇索引。因此,当使用约束创建索引时,索引的类型和特征基本上都已经确定了,由用户定制的余地比较小。 

    当在表上定义主键或者唯一性键约束时,如果表 中已经有了使用CREATE INDEX语句创建的标准索引时,那么主键约束或者唯一性键约束创建的索引覆盖以前创建的标准索引。也就是说,主键约束或者唯一性键约束创建的索引的优先 级高于使用CREATE INDEX语句创建的索引。 

    索引的特征 
    索引有两个特征,即唯一性索引和复合索引。
     
    唯一 性索引保证在索引列中的全部数据是唯一的,不会包含冗余数据。如果表中已经有一个主键约束或者唯一性键约束,那么当创建表或者修改表时,SQL Server自动创建一个唯一性索引。然而,如果必须保证唯一性,那么应该创建主键约束或者唯一性键约束,而不是创建一个唯一性索引。当创建唯一性索引 时,应该认真考虑这些规则:当在表中创建主键约束或者唯一性键约束时,SQL Server自动创建一个唯一性索引;如果表中已经包含有数据,那么当创建索引时,SQL Server检查表中已有数据的冗余性;每当使用插入语句插入数据或者使用修改语句修改数据时,SQL Server检查数据的冗余性:如果有冗余值,那么SQL Server取消该语句的执行,并且返回一个错误消息;确保表中的每一行数据都有一个唯一值,这样可以确保每一个实体都可以唯一确认;只能在可以保证实体 完整性的列上创建唯一性索引,例如,不能在人事表中的姓名列上创建唯一性索引,因为人们可以有相同的姓名。 

    复合索引就是一个索引创建
    在两个列或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。当创建复合索引时,应该考虑这些规则:最多可以把16个列合并成一个单独的复合索引,构成复合索引的列的总长度不能超过900字节,也就是说复合列的长度不能太长;在复合索引中,所 有的列必须来自同一个表中,不能跨表建立复合列;在复合索引中,列的排列顺序是非常重要的,因此要认真排列列的顺序,原则上,应该首先定义最唯一的列,例 如在(COL1,COL2)上的索引与在(COL2,COL1)上的索引是不相同的,因为两个索引的列的顺序不同;为了使查询优化器使用复合索引,查询语 句中的WHERE子句必须参考复合索引中第一个列;当表中有多个关键列时,复合索引是非常有用的;使用复合索引可以提高查询性能,减少在一个表中所创建的 索引数量。

     

    5.索引的类型 
    根据索引的顺序与数据表的物理顺序是否相同,可以把索引分成两种类型。一种是数据表的物理顺序与索引顺序相同的聚簇索引,另一种是数据表的物理顺序与索引顺序不相同的非聚簇索引。 

    聚簇索引

    所谓聚簇索引,就是指主索引文件和数据文件为同一份文件,聚簇索引主要用在Innodb存储引擎中。在该索引实现方式中B+Tree的叶子节点上的data就是数据本身,key为主键,如果是一般索引的话,data便会指向对应的主索引,如下图所示:

    在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能,例如图4中如果要查询key为从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。

    非聚簇索

     

    非聚簇索引就是指B+Tree的叶子节点上的data,并不是数据本身,而是数据存放的地址。主索引和辅助索引没啥区别,只是主索引中的key一定得是唯一的。主要用在MyISAM存储引擎中,如下图:

    非聚簇索引比聚簇索引多了一次读取数据的IO操作,所以查找性能上会差。

    MyisAM索引与InnoDB索引相比较

    • MyisAM支持全文索引(FULLTEXT)、压缩索引,InnoDB不支持;
    • InnoDB支持事务,MyisAM不支持;
    • MyisAM顺序储存数据,索引叶子节点保存对应数据行地址,辅助索引很主键索引相差无几;InnoDB主键节点同时保存数据行,其他辅助索引保存的是主键索引的值;
    • MyisAM键值分离,索引载入内存(key_buffer_size),数据缓存依赖操作系统;InnoDB键值一起保存,索引与数据一起载入InnoDB缓冲池;MyisAM主键(唯一)索引按升序来存储存储,InnoDB则不一定
    • MyisAM索引的基数值(Cardinality,show index 命令可以看见)是精确的,InnoDB则是估计值。这里涉及到信息统计的知识,MyisAM统计信息是保存磁盘中,在alter表或Analyze table操作更新此信息,而InnoDB则是在表第一次打开的时候估计值保存在缓存区内;
    • MyisAM处理字符串索引时用增量保存的方式,如第一个索引是‘preform’,第二个是‘preformence’,则第二个保存是‘7,ance’,这个明显的好处是缩短索引,但是缺陷就是不支持倒序提取索引,必须顺序遍历获取索引

    为什么选用B+/-Tree

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

    简单点说说内存读取,内存是由一系列的存储单元组成的,每个存储单元存储固定大小的数据,且有一个唯一地址。当需要读内存时,将地址信号放到地址总线上传给内存,内存解析信号并定位到存储单元,然后把该存储单元上的数据放到数据总线上,回传。

    写内存时,系统将要写入的数据和单元地址分别放到数据总线和地址总线上,内存读取两个总线的内容,做相应的写操作。

    内存存取效率,跟次数有关,先读取A数据还是后读取A数据不会影响存取效率。而磁盘存取就不一样了,磁盘I/O涉及机械操作。磁盘是由大小相同且同轴的圆形盘片组成,磁盘可以转动(各个磁盘须同时转动)。磁盘的一侧有磁头支架,磁头支架固定了一组磁头,每个磁头负责存取一个磁盘的内容。磁头不动,磁盘转动,但磁臂可以前后动,用于读取不同磁道上的数据。磁道就是以盘片为中心划分出来的一系列同心环(如图标红那圈)。磁道又划分为一个个小段,叫扇区,是磁盘的最小存储单元。

    磁盘读取时,系统将数据逻辑地址传给磁盘,磁盘的控制电路会解析出物理地址,即哪个磁道哪个扇区。于是磁头需要前后移动到对应的磁道,消耗的时间叫寻道时间,然后磁盘旋转将对应的扇区转到磁头下,消耗的时间叫旋转时间。所以,适当的操作顺序和数据存放可以减少寻道时间和旋转时间。
    为了尽量减少I/O操作,磁盘读取每次都会预读,大小通常为页的整数倍。即使只需要读取一个字节,磁盘也会读取一页的数据(通常为4K)放入内存,内存与磁盘以页为单位交换数据。因为局部性原理认为,通常一个数据被用到,其附近的数据也会立马被用到。

    B-Tree:如果一次检索需要访问4个节点,数据库系统设计者利用磁盘预读原理,把节点的大小设计为一个页,那读取一个节点只需要一次I/O操作,完成这次检索操作,最多需要3次I/O(根节点常驻内存)。数据记录越小,每个节点存放的数据就越多,树的高度也就越小,I/O操作就少了,检索效率也就上去了。

    B+Tree:非叶子节点只存key,大大滴减少了非叶子节点的大小,那么每个节点就可以存放更多的记录,树更矮了,I/O操作更少了。所以B+Tree拥有更好的性能。

     

    • 索引分类
    ○ 直接创建索引和间接创建索引
    ○ 普通索引和唯一性索引
    ○ 单个索引和复合索引
    ○ 聚簇索引和非聚簇索引

    • 索引失效

    1. 如果条件中有or,即使其中有条件带索引也不会使用(这就是为什么尽量少使用or的原因)(注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)
    2. 对于多列索引,不是使用的第一部分(不符合最左前缀原则),则不会使用索引,例子如下:
      如果select * from key1=1 and key2= 2;则建立组合索引(key1,key2);
      select * from key1 = 1;组合索引有效;
      select * from key1 = 1 and key2= 2;组合索引有效;
      select * from key2 = 2;组合索引失效;不符合最左前缀原则
    3. like查询是以%开头
    4. 如果列类型是字符串,那一定要在条件中使用引号引起来,否则不会使用索引
    5. 如果mysql估计使用全表扫描比使用索引快,则不使用索引
    展开全文
  • 1.什么是索引?为什么要用索引? 1.1索引的含义 1.2为什么用? 2.索引的作用与缺点 2.1作用 2.2缺点 3.索引的使用场景 3.1应创建索引的场景 3.2不应创建索引的场景 4.索引的分类与说明 4.1主键索引 ...

    热门系列:


    目录

    1.什么是索引?为什么要用索引?

       1.1索引的含义

       1.2为什么用?

    2.索引的作用与缺点

       2.1作用

       2.2缺点

    3.索引的使用场景

      3.1应创建索引的场景

      3.2不应创建索引的场景

    4.索引的分类与说明

      4.1主键索引

      4.2单列索引

      4.3唯一索引

      4.4复合索引

      4.5聚集索引与非聚集索引

         4.5.1聚集索引

         4.5.2非聚集索引

         4.5.3使用及语法

         4.5.4使用场景对比

      4.6聚簇索引与非聚簇索引

         4.6.1聚簇索引

         4.6.2非聚簇索引

         4.6.3Mysql的MYISAM和INNODB引擎

         4.6.4对比总结

     4.7稠密索引与稀疏索引

         4.7.1稠密索引

         4.7.2稀疏索引

    5.索引的底层原理

         5.1 B-Tree

         5.2 B+Tree

         5.3 B-树和B+树的区别

    6.总结


    1.什么是索引?为什么要用索引?

      1.1索引的含义

    数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询,更新数据库中表的数据.索引的实现通常使用B树和变种的B+树(mysql常用的索引就是B+树)。除了数据之外,数据库系统还维护为满足特定查找算法的数据结构,这些数据结构以某种方式引用数据.这种数据结构就是索引!

    简言之,索引就类似于书本,字典的目录!

      1.2为什么用?

    打个比方,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢。

    一言以蔽之,合理使用索引,可以加快数据库的查询效率和提升程序性能!


    2.索引的作用与缺点

      2.1作用

       ①通过创建索引,可以在查询的过程中,提高系统的性能

       ②通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性

       ③在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的时间

      2.2缺点

       ①创建索引和维护索引要耗费时间,而且时间随着数据量的增加而增大

       ②索引需要占用物理空间,如果要建立聚簇索引,所需要的空间会更大

       ③在对表中的数据进行增加删除和修改时需要耗费较多的时间,因为索引也要动态地维护


    3.索引的使用场景

      3.1应创建索引的场景

       ①经常需要搜索的列上

       ②作为主键的列上

       ③经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度

       ④经常需要根据范围进行搜索的列上

       ⑤经常需要排序的列上

       ⑥经常使用在where子句上面的列上

     

      3.2不应创建索引的场景

       ①查询中很少用到的列

       ②对于那些具有很少数据值的列.比如数据表中的性别列,bit数据类型的列

       ③对于那些定义为text,image的列.因为这些列的数据量相当大

       ④当对修改性能的要求远远大于搜索性能时.因为当增加索引时,会提高搜索性能,但是会降低修改性能


    4.索引的分类与说明

      4.1主键索引

       设定为主键后数据库会自动建立索引,innodb为聚簇索引

    #随表一起建索引:
    CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
      PRIMARY KEY(id) 
    );
    #使用AUTO_INCREMENT关键字的列必须有索引(只要有索引就行)。
    CREATE TABLE customer2 (id INT(10) UNSIGNED,customer_no VARCHAR(200),customer_name VARCHAR(200),
      PRIMARY KEY(id) 
    );
    #单独建主键索引:
    ALTER TABLE customer add PRIMARY KEY customer(customer_no);  
    #删除建主键索引:
    ALTER TABLE customer drop PRIMARY KEY ;  
    #修改建主键索引:
    #必须先删除掉(drop)原索引,再新建(add)索引

     

    4.2单列索引

       一个索引只包含单个列,一个表可以有多个单列索引

    #随表一起建索引:
    CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
      PRIMARY KEY(id),
      KEY (customer_name)  
    );
    #随表一起建立的索引 索引名同 列名(customer_name)
    #单独建单值索引:
    CREATE INDEX idx_customer_name ON customer(customer_name); 
    #删除索引:
    DROP INDEX idx_customer_name ;

     

    4.3唯一索引

       索引列的值必须唯一,但允许有空值

    #随表一起建索引:
    CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
      PRIMARY KEY(id),
      KEY (customer_name),
      UNIQUE (customer_no)
    );
    #建立 唯一索引时必须保证所有的值是唯一的(除了null),若有重复数据,会报错。   
    #单独建唯一索引:
    CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no); 
    #删除索引:
    DROP INDEX idx_customer_no on customer ;

     

    4.4复合索引

    一个索引包含多个列,在数据库操作期间,复合索引比单值索引所需要的开销更小(对于相同的多个列建索引)

    如果一个表中的数据在查询时有多个字段总是同时出现则这些字段就可以作为复合索引,形成索引覆盖可以提高查询的效率!

    #随表一起建索引:
    CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
      PRIMARY KEY(id),
      KEY (customer_name),
      UNIQUE (customer_name),
      KEY (customer_no,customer_name)
    );
    #单独建索引:
    CREATE INDEX idx_no_name ON customer(customer_no,customer_name); 
    #删除索引:
    DROP INDEX idx_no_name  on customer ;


      4.5聚集索引与非聚集索引

         4.5.1聚集索引

      聚集索引:指索引项的排序方式和表中数据记录排序方式一致的索引。它会根据聚集索引键的顺序来存储表中的数据,即对表 的数据按索引键的顺序进行排序,然后重新存储到磁盘上。因为数据在物理存放时只能有一种排列方式,所以一个表只能有一个聚集索引。比如字典中,用‘拼音’查汉字,就是聚集索引。因为正文中字都是按照拼音排序的。而用‘偏旁部首’查汉字,就是非聚集索引,因为正文中的字并不是按照偏旁部首排序的,我们通过检字表得到正文中的字在索引中的映射,然后通过映射找到所需要的字。

    聚集索引的使用场合为: 

    • a.查询命令的回传结果是以该字段为排序依据的; 
    • b.查询的结果返回一个区间的值; 
    • c.查询的结果返回某值相同的大量结果集。 

    聚集索引会降低 insert,和update操作的性能,所以,是否使用聚集索引要全面衡量。

     

         4.5.2非聚集索引

    非聚集索引:与聚集索引相反, 索引顺序与物理存储顺序不一致。

    非聚集索引的使用场合为: 

    • a.查询所获数据量较少时; 
    • b.某字段中的数据的唯一性比较高时;

    非聚集索引必须是稠密索引

     

        4.5.3使用及语法

    create [unique] [clustered] [nonclustered] index index_name  on {tabel/view} (column[dese/asc][....n])

    注: [unique] [clustered] [nonclustered]表示要创建索引的类型,以此为唯一索引,聚集索引,和非聚集索引,当省略unique选项时,建立非唯一索引.当省略clustered,nonclustered选项时.建立聚集索引,省略nonclustered选项时,建立唯一聚集索引。

     

        4.5.4使用场景对比

    动作描述使用聚集索引使用非聚集索引
    列经常被分组排序使用使用
    返回某范围内的数据使用不使用
    一个或极少不同值不使用不使用
    小数目的不同值使用不使用
    大数目的不同值不使用使用
    频繁更新的列不使用使用
    外键列使用使用
    主键列使用使用
    频繁修改索引列不使用使用

      4.6聚簇索引与非聚簇索引

        4.6.1聚簇索引

    聚簇索引并不是一种单独的索引类型,而是一种数据存储方式将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。

    聚簇索引的特点:

    聚簇索引具有唯一性,由于聚簇索引是将数据跟索引结构放到一块,因此一个表仅有一个聚簇索引。

    表中行的物理顺序和索引中行的物理顺序是相同的在创建任何非聚簇索引之前创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行 按照一定的顺序排列,并且自动维护这个顺序;

    聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一且非空的索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键(类似oracle中的RowId)来作为聚簇索引。如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。

     

        4.6.2非聚簇索引

    不是聚簇索引的二级索引,也叫辅助索引,都称为非聚簇索引。将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置。

     

        4.6.3Mysql的MYISAM和INNODB引擎

    因为这两种引擎对非聚簇索引和聚簇索引的使用,就是他们之间很大的一个区别。所以结合这两个引擎,再对这两种索引展开些描述就更明了了。

    在innodb中,在聚簇索引之上创建的索引称之为辅助索引,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引。辅助索引叶子节点存储的不再是行的物理位置,而是主键值,辅助索引访问数据总是需要二次查找

    1. InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。
    2. 若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。(重点在于通过其他键需要建立辅助索引)

    MyISAM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树

     

        4.6.4对比总结

    每次使用辅助索引检索都要经过两次B+树查找,看上去聚簇索引的效率明显要低于非聚簇索引,这不是多此一举吗?聚簇索引的优势在哪?

    1.由于行数据和聚簇索引的叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中(缓存器),再次访问时,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。

    2.辅助索引的叶子节点,存储主键值,而不是数据的存放地址。好处是当行数据放生变化时,索引树的节点也需要分裂变化;或者是我们需要查找的数据,在上一次IO读写的缓存中没有,需要发生一次新的IO操作时,可以避免对辅助索引的维护工作,只需要维护聚簇索引树就好了。另一个好处是,因为辅助索引存放的是主键值,减少了辅助索引占用的存储空间大小。

    注:我们知道一次io读写,可以获取到16K大小的资源,我们称之为读取到的数据区域为Page。而我们的B树,B+树的索引结构,叶子节点上存放好多个关键字(索引值)和对应的数据,都会在一次IO操作中被读取到缓存中,所以在访问同一个页中的不同记录时,会在内存里操作,而不用再次进行IO操作了。除非发生了页的分裂,即要查询的行数据不在上次IO操作的换村里,才会触发新的IO操作。

    3.因为MyISAM的主索引并非聚簇索引,那么他的数据的物理地址必然是凌乱的,拿到这些物理地址,按照合适的算法进行I/O读取,于是开始不停的寻道不停的旋转。聚簇索引则只需一次I/O。(强烈的对比)

    4.不过,如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。

    5.当使用主键为聚簇索引时,主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能出线新增加记录的uuid,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。建议使用int类型的自增,方便排序并且默认会在索引树的末尾增加主键值,对索引树的结构影响最小。而且,主键值占用的存储空间越大,辅助索引中保存的主键值也会跟着变大,占用存储空间,也会影响到IO操作读取到的数据量。


      4.7稠密索引与稀疏索引

    在了解稠密索引和稀疏索引之前我们先来了解一下什么是聚焦索引。在一个文件中,可以有多个索引,分别基于不同的搜索码。如果包含数据记录的文件按照某个指定的顺序排列,那么该搜索码对应的索引就是聚焦索引。

        4.7.1稠密索引

    在稠密索引中,文件中的每个搜索码值都对应一个索引值。也就是说,稠密索引为数据记录文件的每一条记录都设一个键-指针对。如下图所示,索引项包括索引值以及指向该搜索码的第一条数据记录的指针,即我们所说的键-指针对。

       4.7.2稀疏索引

    在稀疏索引中,只为搜索码的某些值建立索引项。也就是说,稀疏索引为数据记录文件的每个存储块设一个键-指针对,存储块意味着块内存储单元连续。如下图所示。


    5.索引的底层原理

    此节我们抛开其他的数据库索引实现,主讲Mysql的索引底层实现。说到Mysql的索引,了解过的人应该知道,其底层是通过B+数来实现的数据结构存储。

    数据存储结构,决定了数据查找和操作时的效率,包括时间复杂度和空间复杂度。而在取舍的时候,也无非就是时间换空间,空间换时间的权衡罢了。所以,这就很好的解释了,为什么Mysql在索引的底层设计上,选用了B+数,而没有选用B-树,或是红黑树,AVL树等等其他数据结构。总之,就是使用B+树作为索引的结构存储,能在I/O性能上得到一个较大的优势。

    那么具体优势在哪里呢?咱们继续往下看。

    本章我们以B-树与B+树的对比,来阐述具体差异和B+树的优势。

     

      5.1 B-Tree

    B-树是一种多路自平衡的搜索树 它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点。B-Tree 相对于 AVLTree 缩减了节点个数,使每次磁盘 I/O 取到内存的数据都发挥了作用,从而提高了查询效率。

    注:B-Tree就是我们常说的B树

    那么m阶 B-Tree 是满足下列条件的数据结构:

    • 所有键值分布在整颗树中
    • 搜索有可能在非叶子结点结束,在关键字全集内做一次查找,性能逼近二分查找
    • 每个节点最多拥有m个子树
    • 根节点至少有2个子树
    • 分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点)
    • 所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列
       

    每个节点占用一个磁盘块,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为 17 和 35,P1 指针指向的子树的数据范围为小于 17,P2 指针指向的子树的数据范围为 17~35,P3 指针指向的子树的数据范围为大于 35。

    模拟查找关键字 29 的过程:

    1. 根据根节点找到磁盘块 1,读入内存。【磁盘 I/O 操作第 1 次】
    2. 比较关键字 29 在区间(17,35),找到磁盘块 1 的指针 P2。
    3. 根据 P2 指针找到磁盘块 3,读入内存。【磁盘 I/O 操作第 2 次】
    4. 比较关键字 29 在区间(26,30),找到磁盘块 3 的指针 P2。
    5. 根据 P2 指针找到磁盘块 8,读入内存。【磁盘 I/O 操作第 3 次】
    6. 在磁盘块 8 中的关键字列表中找到关键字 29。
    7. 分析上面过程,发现需要 3 次磁盘 I/O 操作,和 3 次内存查找操作。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。而 3 次磁盘 I/O 操作是影响整个 B-Tree 查找效率的决定因素。

    但同时B-Tree也存在问题:

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

     

    5.2 B+Tree

    B+Tree 是在 B-Tree 基础上的一种优化,InnoDB 存储引擎就是用 B+Tree 实现其索引结构。它带来的变化点:

    • B+树每个节点可以包含更多的节点,这样做有两个原因,一个是降低树的高度。另外一个是将数据范围变为多个区间,区间越多,数据检索越快
    • 非叶子节点存储key,叶子节点存储key和数据
    • 叶子节点两两指针相互链接(符合磁盘的预读特性),顺序查询性能更高

    注:MySQL 的 InnoDB 存储引擎在设计时是将根节点常驻内存的,因此力求达到树的深度不超过 3,也就是说 I/O 不需要超过 3 次。

    通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找

     

    5.3 B-树和B+树的区别

    • B+树内节点不存储数据,所有数据存储在叶节点导致查询时间复杂度固定为 log n
    • B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)
    • B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等
    • B+树更适合外部存储(存储磁盘数据)。由于内节点无 data 域,每个节点能索引的范围更大更精确。
       

    6.总结

        本章内容其实是我个人对索引这块的知识点的巩固与梳理。之前有很多总结,比较零散,趁当下有点时间,所以整理了出来。其中还有很多不足,或是有瑕疵的地方,若有不对之处,尽情拍砖指正。最后,也希望能够帮助到,正在学习的你,加油!

     

    本博客皆为学习、分享、探讨为本,欢迎各位朋友评论、点赞、收藏、关注,一起加油!

     

    展开全文
  • 数据库索引怎么实现的

    千次阅读 2019-12-15 20:44:49
    数据库索引怎么实现的 (招银网络科技java面经) 目录 数据库索引怎么实现的 1 简介 2索引是如何工作的 简介 索引数据结构类型 哈希表 有序数组 搜索树 索引是怎么提升性能的? 3 优缺点 4 如何合理...

                                      数据库索引怎么实现的

    (招银网络科技java面经)

     

    目录

                                      数据库索引怎么实现的

    1 简介

    2索引是如何工作的

    简介

    索引数据结构类型

    哈希表

    有序数组

    搜索树

    索引是怎么提升性能的?

    3 优缺点

    4 如何合理的建立索引

    应该创建索引的

    不应该创建索引的

    联合索引是什么?为什么需要注意联合索引中的顺序

    5 索引的类型

    唯一索引 

    主键索引

    聚集索引

    6 局部性原理与磁盘预读

    7 有关文章


    1 简介

    数据库索引是数据库管理系统中一个排序的数据结构以协助快速查询、更新数据库表中数据。

    在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

    索引的数据结构和具体存储引擎的实现有关, 在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引.

     

    为表设置索引要付出代价的:一是增加了数据库的存储空间二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)

     

    上图展示了一种可能的索引方式。左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址(注意逻辑上相邻的记录在磁盘上也并不是一定物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在O(log2n)的复杂度内获取到相应数据。

    2索引是如何工作的

    简介

    首先明白为什么索引会增加速度,DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。那么在任何时候都应该加索引么?

     

    使用索引的全部意义就是通过缩小一张表中需要查询的记录/行的数目来加快搜索的速度一个索引是存储的表中一个特定列的值数据结构(最常见的是B-Tree)。索引是在表的列上创建。所以,要记住的关键点是索引包含一个表中列的值,并且这些值存储在一个数据结构中。请记住记住这一点:索引是一种数据结构 。

    索引数据结构类型

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

    哈希表

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

     

    不可避免地,多个key值经过哈希函数的换算,会出现同一个值的情况。处理这种情况的一种方法是,拉出一个链表。

     

    User2和User4根据身份证号算出来的值都是N,但没关系,后面还跟了一个链表。假设,这时候你要查ID_card_n2对应的名字是什么,处理步骤就是:首先,将ID_card_n2通过哈希函数算出N;然后,按顺序遍历,找到User2。

     

    图中四个ID_card_n的值并不是递增的,这样做的好处是增加新的User时速度会很快,只需要往后追加。但缺点是,因为不是有序的,所以哈希索引做区间查询的速度是很慢的。

     

    你可以设想下,如果你现在要找身份证号在[ID_card_X, ID_card_Y]这个区间的所有用户,就必须全部扫描一遍了。

     

    哈希表这种结构适用于只有等值查询的场景,比如Memcached及其他一些NoSQL引擎。

    有序数组在等值查询和范围查询场景中的性能就都非常优秀。还是上面这个根据身份证号查名字的例子,如果我们使用有序数组来实现的话,示意图如下所示:

    有序数组

    有序数组在等值查询和范围查询场景中的性能就都非常优秀。还是上面这个根据身份证号查名字的例子,如果我们使用有序数组来实现的话,示意图如下所示:

     

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

     

    同时很显然,这个索引结构支持范围查询。你要查身份证号在[ID_card_X, ID_card_Y]区间的User,可以先用二分法找到ID_card_X(如果不存在ID_card_X,就找到大于ID_card_X的第一个User),然后向右遍历,直到查到第一个大于ID_card_Y的身份证号,退出循环。

     

    如果仅仅看查询效率,有序数组就是最好的数据结构了。但是,在需要更新数据的时候就麻烦了,你往中间插入一个记录就必须得挪动后面所有的记录,成本太高。

     

    所以,有序数组索引只适用于静态存储引擎,比如你要保存的是2017年某个城市的所有人口信息,这类不会再修改的数据。

    搜索树

    二叉搜索树也是课本里的经典数据结构了。还是上面根据身份证号查名字的例子,如果我们用二叉搜索树来实现的话,示意图如下所示:

     

    B-Tree 是最常用的用于索引的数据结构。因为它们是时间复杂度低, 查找、删除、插入操作都可以可以在对数时间内完成。另外一个重要原因存储在B-Tree中的数据是有序的。数据库管理系统(RDBMS)通常决定索引应该用哪些数据结构。但是,在某些情况下,你在创建索引时可以指定索引要使用的数据结构。

    索引是怎么提升性能的?

    因为索引基本上是用来存储列值的数据结构,这使查找这些列值更加快速。如果索引使用最常用的数据结构-B-Tree-那么其中的数据是有序的。有序的列值可以极大的提升性能。下面解释原因。

     

    假设我们在 Employee_Name这一列上创建一个B-Tree索引。这意味着当我们用之前的SQL查找姓名是‘Jesus’的雇员时,不需要再扫描全表。而是用索引查找去查找名字为‘Jesus’的雇员,因为索引已经按照按字母顺序排序。索引已经排序意味着查询一个名字会快很多,因为名字少字母为‘J’的员工都是排列在一起的。另外重要的一点是,索引同时存储了表中相应行的指针以获取其他列的数据。

    数据库索引里究竟存的是什么?

    你现在已经知道数据库索引是创建在表的某列上的,并且存储了这一列的所有值。但是,需要理解的重点是数据库索引并不存储这个表中其他列(字段)的值。举例来说,如果我们在Employee_Name列创建索引,那么列Employee_Age和Employee_Address上的值并不会存储在这个索引当中。如果我们确实把其他所有字段也存储在个这个索引中,那就成了拷贝一整张表做为索引-这样会占用太大的空间而且会十分低效。

    索引存储了指向表中某一行的指针

    如果我们在索引里找到某一条记录作为索引的列的值,如何才能找到这一条记录的其它值呢?这是很简单 - 数据库索引同时存储了指向表中的相应行的指针。指针是指一块内存区域, 该内存区域记录的是对硬盘上记录的相应行的数据的引用。因此,索引中除了存储列的值,还存储着一个指向在行数据的索引。也就是说,索引中的Employee_Name这列的某个值(或者节点)可以描述为 (“Jesus”, 0x82829), 0x82829 就是包含 “Jesus”那行数据在硬盘上的地址。如果没有这个引用,你就只能访问到一个单独的值(“Jesus”),而这样没有意义,因为你不能获取这一行记录的employee的其他值-例如地址(address)和年龄(age)。

    3 优缺点

    创建索引可以大大提高系统的性能。

    第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

    第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

    第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

    第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

    第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

     

    也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?因为,增加索引也有许多不利的方面。

    第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。(时间)

    第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。(空间)

    第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。(维护)

    4 如何合理的建立索引

    应该创建索引的

    索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:

    1 在经常需要搜索的列上,可以加快搜索的速度;(字段的使用频率

    2 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

    3 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

    4 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

    5在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

    6 经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

    不应该创建索引的

    同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:

    1于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

    2对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

    3对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

    4当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

    联合索引是什么?为什么需要注意联合索引中的顺序

    MySQL可以使用多个字段同时建立一个索引,叫做联合索引.在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引.

    具体原因为:

    MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序.

    当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,,,以此类推.因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面.此外可以根据特例的查询或者表结构进行单独的调整.

    5 索引的类型

    根据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引。

    唯一索引 

    唯一索引是不允许其中任何两行具有相同索引值的索引。

    当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在employee表中职员的姓(lname)上创建了唯一索引,则任何两个员工都不能同姓。

    主键索引

    数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。

    在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。

    聚集索引

    在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。

    如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。

    6 局部性原理与磁盘预读

    由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中。

    由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

    预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k)主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

     

    7 有关文章

    https://blog.csdn.net/weixin_41563161/article/details/101227932

    数据库基本知识

    https://blog.csdn.net/weixin_41563161/article/details/102457643

    mysql45深入浅出索引

    https://blog.csdn.net/weixin_41563161/article/details/102737347#1.%20什么是索引%3F

     数据库常见面试知识

    https://blog.csdn.net/weixin_41563161/article/details/102966786

    mysql45怎么给字符串字段加索引?

    https://blog.csdn.net/weixin_41563161/article/details/102859171

    mysql45普通索引和唯一索引,应该怎么选择?

    https://blog.csdn.net/weixin_41563161/article/details/102957941

    mysql45 MySQL为什么有时候会选错索引?

    https://blog.csdn.net/weixin_41563161/article/details/101228148

    mysql基本知识

    https://blog.csdn.net/weiliangliang111/article/details/51333169

    数据库索引到底是什么,是怎样工作的?

     

    展开全文
  • 数据库索引实现原理

    万次阅读 多人点赞 2019-04-15 16:28:54
    MySQL索引实现 在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。 MyISAM索引实现 MyISAM引擎使用B+Tree作为索引结构,叶...
  • 数据库索引原理及优化

    千次阅读 2018-08-07 11:03:02
    本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文...
  • 漫谈数据库索引漫谈数据库索引漫谈数据库索引漫谈数据库索引
  • 数据库索引的应用与底层实现

    千次阅读 多人点赞 2018-04-21 02:00:48
    关于数据库索引,它的重要性体现在了方方面面,因此也不约而同的成为了面试中的一大要点。在我近期的腾讯、阿里巴巴面试中数据库索引也确实占据了一些分量,下午去腾讯现场面,还没来得及去看自己不懂的问题,晚上...
  • 数据库索引实例

    千次阅读 2018-08-15 17:10:45
    参考文献: [1].漫谈数据库索引 1.创建表并插入数据 在Sql Server2008中创建测试数据库Test,接着创建数据库表并插入数据,sql代码如下: USE Test IF E
  • MySQL数据库索引教程(超详细)

    千次阅读 多人点赞 2020-12-19 14:30:41
    索引初步 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。 拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。 索引分...
  • MySql数据库索引介绍

    千次阅读 多人点赞 2019-05-27 17:08:27
    数据库索引对我们来说是透明的,因为数据库表创建索引前后,SQL语句都可以正常运行,索引的运用只是数据库引擎工作时候的优化手段。但是,这并不是说数据库索引仅仅是数据库设计开发人员和运维人员的事情,对于一个...
  • 54、数据库索引 索引的优缺点   优点:   1、大大加快数据的检索速度;   2、创建唯一性索引,保证数据库表中每一行数据的唯一性;   3、加速表和表之间的连接;   4、在使用分组和排序子句进行数据检索时...
  • MySQL数据库索引

    万次阅读 多人点赞 2018-09-23 09:31:41
    数据库有哪些索引 唯一索引 聚簇索引与非聚簇索引 全文索引 使用索引一定能提高查询性能吗? 哪些情况下设置了索引但是无法使用 哪些情况下需要设置索引、哪些情况下不需要 什么情况下应该使用组合索引而非...
  • 数据库索引设计(基础篇)

    千次阅读 2020-10-08 09:05:06
    点击蓝色“有关SQL”关注我哟加个“星标”,天天与10000人一起快乐成长索引数据库中,毋庸置疑扮演了极其重要的角色。在这篇文章中,我们即将要讨论这些和索引相关的事情:优化器是如何选择...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 781,398
精华内容 312,559
关键字:

数据库索引