数据库索引如何工作?
鉴于索引是如此重要,因为你的数据集增加的大小,有人可以解释如何索引工作在数据库无关的水平?
有关查询索引字段的信息,请查看如何索引数据库列 。
为什么需要?
当数据存储在基于磁盘的存储设备上时,它将作为数据块存储。 这些块被完整访问,使它们成为primefaces磁盘访问操作。 磁盘块的结构与链接列表非常相似, 都包含数据部分,指向下一个节点(或块)位置的指针,并且都不需要连续存储。
由于许多logging只能在一个字段上sorting的事实,我们可以说,在未sorting的字段上search需要一个线性search,它需要N/2
块的访问(平均),其中N
是表跨越的块数。 如果该字段是非关键字段(即不包含唯一条目),则必须在N
块访问时search整个表空间。
而对于sorting字段,可以使用二进制search,这具有log2 N
块访问。 另外,由于数据是按照非关键字段进行sorting的,因此一旦find更高的值,表格的其余部分就不需要search重复值。 因此,性能提高是相当大的。
什么是索引?
索引是一种对多个字段上的多个logging进行sorting的方法。 在表中的字段上创build索引会创build另一个数据结构,该结构保存字段值以及指向与其相关的logging的指针。 然后对索引结构进行sorting,从而对其执行二进制search。
索引的缺点是这些索引需要额外的磁盘空间,因为索引使用MyISAM引擎一起存储在一个表中,如果同一个表中有很多字段是这样的话,那么这个文件可以很快达到底层文件系统的大小限制索引。
它是如何工作的?
首先,我们来概述一个示例数据库表模式;
字段名称数据types磁盘上的大小 id(主键)无符号整数4字节 firstName Char(50)50个字节 姓氏字符(50)50个字节 emailAddress字符(100)100个字节
注意 :char被用来代替varchar来允许在磁盘值上有一个精确的大小。 此示例数据库包含500万行,并且是未索引的。 现在将分析几个查询的性能。 这些是使用id (sorting的关键字段)的查询和使用firstName (非关键字未sorting的字段)的查询。
示例1 – sorting与未sorting的字段
给定我们的样本数据库r = 5,000,000
个固定大小的logging,logging长度为R = 204
个字节,并使用MyISAM引擎将其存储在一个表中,该引擎使用默认块大小B = 1,024
字节。 该表的阻塞因子是每个磁盘块的bfr = (B/R) = 1024/204 = 5
logging。 保存该表所需的块的总数是N = (r/bfr) = 5000000/5 = 1,000,000
个块。
在id字段上的线性search需要平均N/2 = 500,000
块访问来find一个值,因为id字段是关键字段。 但是由于id字段也被sorting,所以可以进行二分search,要求平均log2 1000000 = 19.93 = 20
块访问。 瞬间我们可以看到这是一个巨大的改进。
现在firstName字段既没有sorting,也没有关键字段,所以二进制search是不可能的,而且这些值也是唯一的,因此表需要search最终的N = 1,000,000
块的访问。 索引的目的是纠正这种情况。
假设一个索引logging只包含索引字段和一个指向原始logging的指针,那么理由是它将小于它指向的多字段logging。 所以索引本身需要比原始表更less的磁盘块,因此需要更less的块访问来迭代。 firstName字段上的索引模式概述如下;
字段名称数据types磁盘上的大小 firstName Char(50)50个字节 (logging指针)特殊4字节
注意 :根据表的大小,MySQL中的指针长度为2,3,4或5个字节。
示例2 – 索引
假设我们的样本数据库的索引logging长度为R = 54
个字节,并且使用默认块大小B = 1,024
字节的r = 5,000,000
条logging。 索引的阻塞因子是每个磁盘块的bfr = (B/R) = 1024/54 = 18
logging。 保存索引所需的块的总数是N = (r/bfr) = 5000000/18 = 277,778
块。
现在使用firstName字段进行search可以利用索引来提高性能。 这允许以平均log2 277778 = 18.08 = 19
块访问的索引进行二进制search。 要find实际logging的地址,这需要进一步的块访问读取,使总数达到19 + 1 = 20
块访问,与在非索引表中寻找firstName匹配所需的1,000,000个块访问相差甚远。
什么时候使用?
鉴于创build索引需要额外的磁盘空间(上述示例中增加了277,778个块,增加了约28%),并且索引太多会导致文件系统大小限制引起的问题,因此必须仔细考虑select正确的字段进行索引。
由于索引只是用来加快在logging中search匹配字段的速度,所以原因在于,仅用于输出的索引字段在进行插入或删除操作时仅浪费磁盘空间和处理时间,因此应该避免。 同样考虑到二进制search的性质,数据的基数或唯一性是重要的。 对基数为2的字段进行索引会将数据拆分为一半,而基数为1,000将返回大约1,000条logging。 如果基数低,效率会降低到线性sorting,如果基数小于logging数的30%,则查询优化器将避免使用索引,从而使索引浪费空间。
我第一次读这个对我很有帮助。 谢谢。
从那时起,我对创build索引的缺点有了一些了解:如果使用一个索引写入表( UPDATE
或INSERT
),则实际上在文件系统中有两个写操作。 一个用于表格数据,另一个用于索引数据(以及对它的引用(和 – 如果聚集 – 表格数据的引出))。 如果表和索引位于相同的硬盘上,则花费更多的时间。 因此,没有索引(堆)的表将允许更快的写入操作。 (如果你有两个索引,最终会有三个写操作,等等)
然而,在两个不同的硬盘上为索引数据和表格数据定义两个不同的位置可以减less/消除增加时间成本的问题。 这需要在所需的硬盘上定义附加文件组和相应文件,并根据需要定义表格/索引位置。
索引的另一个问题是随着数据的插入,随着时间的推移碎片化。 REORGANIZE
帮助,你必须编写例程来完成它。
在某些情况下,堆比索引表更有用,
例如: – 如果你有很多相对的写作,但是只有一个晚上在工作时间以外进行报道。
而且,聚集索引和非聚集索引之间的区别是相当重要的。
帮助我: – 聚集和非聚集索引实际上是什么意思?
索引只是一个数据结构,使数据库中特定列的search速度更快。 这个结构通常是一个B树,但它也可以是一个哈希表或其他逻辑结构。
有关更多信息,我build议这样做:数据库索引如何工作? 而且,索引如何提供帮助?
现在,假设我们想运行一个查询来查找名为'Abc'的所有雇员的所有细节?
SELECT * FROM Employee WHERE Employee_Name = 'Abc'
没有索引会发生什么?
数据库软件从字面上必须查看Employee表中的每一行,以查看该行的Employee_Name是否为'Abc'。 而且,因为我们希望每一行里面都有“Abc”这个名字,所以只要我们find一行名为“Abc”的行,我们就不能停止查找,因为可能会有其他行的名字是Abc 。 因此,直到最后一行为止的每一行都必须被search – 这意味着在这种情况下,数以千计的行将被数据库检查以查找名称为“Abc”的行。 这就是所谓的全表扫描
数据库索引如何帮助性能
具有索引的整个观点是通过基本上减less需要检查的表中的logging/行数来加速search查询。 索引是一个数据结构(最常见的是一个B-树),用于存储表中特定列的值。
B树索引如何工作?
B树是最stream行的索引数据结构的原因是因为它们是时间效率的 – 因为查找,删除和插入都可以在对数时间完成。 而且,B-树更常用的另一个主要原因是因为存储在B-树内的数据可以被sorting。 RDBMS通常确定哪个数据结构实际上用于索引。 但是,在某些使用某些RDBMS的情况下,实际上可以指定在创build索引时希望数据库使用哪种数据结构。
哈希表索引如何工作?
使用哈希索引的原因是因为哈希表在查找值时非常高效。 所以,如果使用散列索引,那么与string相等的查询可以非常快地检索值。
例如,我们前面讨论的查询可以从Employee_Name列上创build的哈希索引中受益。 散列索引的工作方式是列值将成为哈希表的键值,而映射到该键值的实际值只是指向表中的行数据的指针。 由于散列表基本上是一个关联数组,所以典型的条目看起来像“Abc => 0x28939”,其中0x28939是Abc存储在内存中的表行的引用。 在哈希表索引中查找像“Abc”这样的值,并获取对内存中行的引用显然要比扫描表findEmployee_Name列中所有值为“Abc”的行快得多。
散列索引的缺点
哈希表不是有序的数据结构,有很多types的查询,哈希索引甚至不能帮助。 例如,假设你想找出所有40岁以下的员工。 你怎么可以做一个哈希表索引? 那么,这是不可能的,因为散列表只适用于查找键值对 – 这意味着检查相等的查询
数据库索引究竟是什么? 所以,现在你知道一个数据库索引是在一个表中的一列上创build的,并且该索引存储了该特定列中的值。 但是,理解数据库索引不会将值存储在同一个表的其他列中是非常重要的。 例如,如果我们在Employee_Name列上创build一个索引,这意味着Employee_Age和Employee_Address列值也不存储在索引中。 如果我们只是将所有其他列存储在索引中,那么就像创build整个表的另一个副本一样 – 这会占用太多的空间并且效率非常低。
数据库如何知道何时使用索引? 当像“SELECT * FROM Employee WHERE Employee_Name ='Abc'”这样的查询被运行时,数据库将检查被查询的列是否有索引。 假设Employee_Name列确实在其上创build了索引,那么数据库将必须决定使用索引来查找正在search的值是否有意义 – 因为在某些情况下,使用数据库索引实际上效率较低,而且更有效率地扫描整个表格。
有一个数据库索引的成本是多less?
它占用空间 – 而你的桌子越大,你的指数就越大。 索引的另一个性能是,无论何时添加,删除或更新相应表中的行,都必须对索引执行相同的操作。 请记住,索引需要包含与索引覆盖的表列中的任何内容相同的分钟数据。
一般来说,如果索引列中的数据将经常被查询,则只应在表上创build索引。
也可以看看
- 什么专栏通常做出好的指标?
- 数据库索引如何工作?
简单的说明!!!!!!!!!!
索引只不过是一个数据结构,用于存储表中特定列的值。 索引是在表的一列上创build的。
例如,我们有一个名为User的数据库表,其中包含三列 – 名称,年龄和地址。 假定用户表有成千上万的行。
现在,假设我们要运行查询来查找名为“John”的任何用户的所有详细信息。 如果我们运行以下查询。
SELECT * FROM User WHERE Name = 'John'
数据库软件实际上必须查看用户表中的每一行,以查看该行的名称是否为“John”。 这将需要很长时间。
这是索引帮助我们的地方“索引用于通过减less需要检查的表中的logging/行的数量来加速search查询”。
如何创build索引
CREATE INDEX name_index ON User (Name)
索引由一个表中的列值(例如:John)组成,并且这些值存储在数据结构中。
因此,现在数据库将使用索引来查找名为John的员工,因为索引可能会按用户名称的字母顺序sorting。 而且,因为它是sorting的,这意味着search一个名字要快得多,因为以“J”开头的所有名字在索引中都是紧挨着的!
经典示例“书籍索引”
考虑1000页的“书”,除以100个部分,每个部分用X页。
简单,嗯?
现在,在没有索引页的情况下,要find以字母“S”开头的特定部分,除了扫描整本书以外,没有别的select。 即:1000页
但是一开始就有索引页面,你就在那里。 更重要的是,要阅读任何重要的部分,您只需要每次查看索引页面一遍又一遍。 find匹配的索引后,您可以通过跳过其他部分高效地跳转到该部分。
但是,除了1000页以外,还需要另外〜10页才能显示索引页,总共1010页。
因此,索引是一个单独的部分,它将索引logging的数据以sorting顺序存储以便进行高效查找。
事情在学校很简单,不是吗? :P
只是一个快速的build议..作为索引花费额外的写入和存储空间,所以如果你的应用程序需要更多的插入/更新操作,你可能想要使用没有索引的表,但是如果它需要更多的数据检索操作,你应该去索引表。
试想一下数据库索引作为一本书的索引。 如果你有一本关于狗的书,并且你想find关于德国牧羊犬的信息,你当然可以浏览书中的所有页面,find你正在寻找的东西,但这当然是耗时的,而不是很快速。 另一个select是,你可以直接进入本书的索引部分,然后通过使用你正在查找的实体的名称(在这个例子中,德国牧羊犬),并查看页码快速find你要找的东西。 在数据库中,页码被称为指针,它将数据库指向实体所在磁盘上的地址。 使用相同的德国牧羊犬的类比,我们可以有这样的(“德国牧羊犬”,0x77129),其中0x77129是存储德国牧羊犬的行数据的磁盘上的地址。
简而言之,索引是一种数据结构,用于存储表中特定列的值,以加快查询search的速度。
在使用行结构存储的关系数据库中,二级索引存储在远离“基表数据”的单独存储区域中。 在创build索引时,将遍历基表以获取要编制索引的列,这些列将插入到存储的索引结构(通常是B树)中,并保存到持久性表的持久性存储中。
索引条目本身也是“行”,包含索引列和一些到基表数据的偏移量。 当一个索引被用来获取一行时,索引就会被search到,直到find感兴趣的行,然后查找基表来获取实际的行数据。
当一行被插入时,对应的行被写入索引,当一行被删除时,其索引行被取出。
请注意,这就是为什么索引占用空间的原因,以及为什么有很多索引会减慢对基表的写入操作:索引必须与表保持同步,因此对于每个INSERT或DELETE到基础表,在索引中进行活动,并且对基础表进行更新(即使更新的列不在索引中)也可能触发索引活动,以及某些基表数据存储pipe理器存储可能需要更新的行偏移。
确切的行为取决于存储引擎的实现。
一些存储引擎通常在PRIMARY KEY上实现“主索引”。 这种types的最常用的存储引擎是MySQL InnoDB–在这种情况下,基本表数据本身存储在B-Tree结构中,次要索引存储每行的PRIMARY KEY。 Oracle的“索引组织表”也是这样实现的。
这种结构的一大优点是在PRIMARY KEY上的查找速度非常快,因为只有一个结构必须被访问来提取行,而传统的“堆+二级索引”存储只能访问两个结构。
索引有许多有趣的变化:“不完整的”索引,意味着只有满足属性才加载的索引(如果你有一个庞大的表,但通常search特定的列值,那么这些索引是有用的),“基于函数的”索引,其中索引值是在一个函数上计算的,等PostgreSQL有很多这些。
有很多工具可以帮助,但我目前正在使用SQLDbm ,我发现最有效的。 也许你应该检查出来。
您可以将索引视为黄页书籍。 它可以快速向您显示在哪里find所需的数据,而不是挨家挨户询问是否是这样。 简单的谷歌search可以产生超过一些好的结果,但是,我发现最帮助我的是: 关于SQL Server索引的十大问题和答案
只是一个快速的build议..作为索引花费额外的写入和存储空间,所以如果你的应用程序需要更多的插入/更新操作,你可能想要使用没有索引的表,但是如果它需要更多的数据检索操作,你应该去索引所以按照这种方式进行数据库索引工作。 点击这里