数据库索引

数据库索引

索引就是为了提高查询性能而存在的, 如果在查询中索引没有提高性能, 只能说是用错了索引,或者讲是场合不同

字段1 字段2 字段3
Employee_Name Employee_Age Employee_Address
SELECT * FROM Employee 
WHERE Employee_Name = 'Jesus'

不加索引 -> 全表扫描

使用索引的全部意义就是通过缩小一张表中需要查询的记录/行的数目来加快搜索的速度

一、索引概念:

一个索引是存储的表中一个特定列的值数据结构(最常见的是B-Tree)。索引是在表的列上创建。所以,要记住的关键点是索引包含一个表中列的值,并且这些值存储在一个数据结构中。请记住记住这一点:索引是一种数据结构 。

一个非常好的类比是把数据库索引看作是书的索引
如果你有一本关于狗的书,你想要找关于‘黄金猎犬’的那部分。当你可以通过在书背的索引找到哪几页有关于‘黄金猎犬’信息的时候,你为什么要翻完正本书 - 这相当于数据库中的全表扫描。同样的,就像一本书的索引包含页码一样,数据库的索引包含了指针,指向你在SQL中想要查询的值所在的行。

(1)B-Tree索引结构

B-Tree 是最常用的用于索引的数据结构。

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

(2)哈希表索引

哈希表是另外一种你可能看到用作索引的数据结构,这些索引通常被称为哈希索引。
使用哈希索引的原因是,在寻找值时哈希表效率极高。所以,如果使用哈希索引,对于比较字符串是否相等的查询能够极快的检索出的值。

例如之前我们讨论过的这个查询(SELECT * FROM Employee WHERE Employee_Name = ‘Jesus’) 就可以受益于创建在Employee_Name 列上的哈希索引。

哈系索引的工作方式是将列的值作为索引的键值(key),和键值相对应实际的值(value)是指向该表中相应行的指针。因为哈希表基本上可以看作是关联数组,一个典型的数据项就像“Jesus => 0x28939″,而0x28939是对内存中表中包含Jesus这一行的引用。在哈系索引的中查询一个像“Jesus”这样的值,并得到对应行的在内存中的引用,明显要比扫描全表获得值为“Jesus”的行的方式快很多。

哈希索引的缺点

哈希表是无顺的数据结构,对于很多类型的查询语句哈希索引都无能为力。

举例来说,假如你想要找出所有小于40岁的员工。你怎么使用使用哈希索引进行查询?这不可行,因为哈希表只适合查询键值对,也就是说查询相等的查询(例:like “WHERE name = ‘Jesus’)。

哈希表的键值映射也暗示其键的存储是无序的。这就是为什么哈希索引通常不是数据库索引的默认数据结构,因为在作为索引的数据结构时,其不像B-Tree那么灵活

(3)其他类型的索引

  1. 使用R-Tree作为数据结构的索引通常用来为空间问题提供帮助。
    例如,一个查询要求“查询出所有距离我两公里之内的星巴克”,如果数据库表使用R- Tree索引,这类查询的效率将会提高。
  2. 另一种索引是位图索引(bitmap index), 这类索引适合放在包含布尔值(true 和 false)的列上,但是这些值(表示true或false的值)的许多实例 ,基本上都是选择性(selectivity)低的列。

(4)索引中存储的是什么

因为索引基本上是用来存储列值的数据结构,这使查找这些列值更加快速。
如果索引使用最常用的数据结构 B-Tree,那么其中的数据是有序的。
有序的列值可以极大的提升性能。下面解释原因:
假设我们在 Employee_Name 这一列上创建一个 B-Tree 索引。这意味着当我们用之前的SQL查找姓名是‘Jesus’的雇员时,不需要再扫描全表。而是用索引查找去查找名字为‘Jesus’的雇员,因为索引已经按照按字母顺序排序。索引已经排序意味着查询一个名字会快很多,因为名字少字母为‘J’的员工都是排列在一起的。另外重要的一点是,索引同时存储了表中相应行的指针以获取其他列的数据。

(5)索引存储指向数据库某行的指针

如果我们在索引里找到某一条记录作为索引的列的值,如何才能找到这一条记录的其它值呢?

数据库索引同时存储了指向表中的相应行的指针。指针是指一块内存区域, 该内存区域记录的是对硬盘上记录的相应行的数据的引用。

因此,索引中除了存储列的值,还存储着一个指向其所在行数据的索引。

也就是说,索引中的Employee_Name这列的某个值(或者节点)可以描述为 (“Jesus”, 0x82829), 0x82829 就是包含 “Jesus”那行数据在硬盘上的地址。如果没有这个引用,你就只能访问到一个单独的值(“Jesus”),而这样没有意义,因为你不能获取这一行记录的employee的其他值,例如地址(address)和年龄(age)。

(6)数据库怎么知道什么时候使用索引

当这个SQL (SELECT * FROM Employee WHERE Employee_Name = ‘Jesus’ )运行时,数据库会检查在查询的列上是否有索引。假设 Employee_Name列上确实创建了索引,数据库会接着检查使用这个索引做查询是否合理 ,因为有些场景下,使用索引比起全表扫描会更加低效。
如果想要了解更多这些场景,请阅读这篇文章:SQL选择性值

那么,什么时候最好使用数据库索引呢?

好吧,当选择性值低时!为什么选择性低意味着使用索引不是一个好主意?好吧,想想看-假设我们要运行一个查询,以查找表中所有女性的名字-我们当然假设“性别”列之外还有“姓名”列。如果我们要搜索具有10,000行的表中的所有女性行,那么很有可能50%的行是女性,因为实际上只有两个可能的值-男性和女性。假设确实有50%的行是女性,那么这意味着我们必须访问索引5,000次才能找到所有的女性行。访问索引需要花费时间,并消耗资源。 如果我们要访问索引5,000次,则直接访问表并进行全表扫描实际上要快一些。因此,您可以看到查询优化器使用了选择性值来确定使用索引还是直接读取表更有效。

通常来说, 开发者不会告诉数据库什么时候使用索引,这是由数据库自己决定。
然而,值得注意的是在大多数数据库中(像Oracle 和 MYSQL), 你实际上可以制订你想要使用的索引。

二、索引的优点

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

三、索引的缺点:

数据库索引是创建在表的某列上的,并且存储了这一列的所有值。

但是,需要理解的重点是数据库索引并不存储这个表中其他列(字段)的值

举例来说,如果我们在Employee_Name列创建索引,那么列Employee_AgeEmployee_Address上的值并不会存储在这个索引当中。如果我们确实把其他所有字段也存储在个这个索引中,那就成了拷贝一整张表做为索引,这样会占用太大的空间而且会十分低效。

  1. 其一,索引会占用空间 ,你的表越大,索引占用的空间越大。
  2. 其二,性能损失(主要值更新操作),当你在表中添加、删除或者更新行数据的时候, 在索引中也会有相同的操作。记住:建立在某列(或多列)索引需要保存该列最新的数据

基本原则是只如果表中某列在查询过程中使用的非常频繁,那就在该列上创建索引

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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容

  • 我们通过一个简单的例子来开始教程,解释为什么我们需要数据库索引。假设我们有一个数据库表 Employee, 这个表...
    田旭1阅读 14,153评论 3 41
  • 引入 场景假设我们有一个数据库表 Employee, 这个表有三个字段(列)分别是 Employee_Name、E...
    一手好厨艺的IT民工阅读 668评论 0 4
  • 索引的基本原理,以及数据是如何被访问的 (一)SQLS如何访问没有建立索引的数据表 Heap译成汉语叫做“堆”,其...
    安易学车阅读 3,446评论 0 8
  • 二、索引 1.什么是索引? 何为索引:数据库索引,是数据库管理系统中一个排序的数据结构,索引的实现通常使用B树及其...
    仁安天下阅读 126评论 0 0
  • 索引 (在 MySQL 中也叫作 “键(key)”) 是存储引擎用于快速找到记录的一种数据结构 索引基础 索引可包...
    cb_guo阅读 549评论 0 2