鉴于随着数据集大小的增加,索引非常重要,有人可以解释索引如何在与数据库无关的级别上工作吗?

有关索引字段的查询的信息,请查看 如何为数据库列建立索引.

有帮助吗?

解决方案

为什么需要它?

当数据存储在基于磁盘的存储设备上时,它被存储为数据块。这些块被完整地访问,使它们成为原子磁盘访问操作。磁盘块的结构与链表非常相似;两者都包含数据部分、指向下一个节点(或块)位置的指针,并且两者不需要连续存储。

由于多条记录只能在一个字段上排序,我们可以说,在未排序的字段上搜索需要线性搜索,这需要 N/2 块访问(平均),其中 N 是表跨越的块数。如果该字段是非关键字段(即不包含唯一条目),则必须在以下位置搜索整个表空间 N 块访问。

而对于排序字段,可以使用二分搜索,它具有 log2 N 块访问。此外,由于数据是根据给定的非键字段进行排序的,因此一旦找到更高的值,就不需要搜索表的其余部分来查找重复值。因此,性能的提升是显着的。

什么是索引?

索引是一种对多个字段上的大量记录进行排序的方法。在表中的字段上创建索引会创建另一个数据结构,该数据结构保存字段值以及指向与其相关的记录的指针。然后对该索引结构进行排序,从而允许对其执行二分搜索。

索引的缺点是这些索引需要额外的磁盘空间,因为索引使用 MyISAM 引擎一起存储在表中,如果对同一个表中的许多字段建立索引,则该文件很快就会达到底层文件系统的大小限制。

它是如何工作的?

首先,让我们概述一个示例数据库表架构;

Field name       Data type      Size on disk
id (Primary key) Unsigned INT   4 bytes
firstName        Char(50)       50 bytes
lastName         Char(50)       50 bytes
emailAddress     Char(100)      100 bytes

笔记: :使用 char 代替 varchar 是为了获得准确的磁盘大小值。此示例数据库包含 500 万行并且未建立索引。现在将分析几个查询的性能。这些是使用以下查询 ID (一个排序的关键字段)和一个使用 (非键未排序字段)。

实施例1 - 已排序字段与未排序字段

鉴于我们的样本数据库 r = 5,000,000 固定大小的记录,记录长度为 R = 204 字节,它们使用 MyISAM 引擎存储在表中,该引擎使用默认的块大小 B = 1,024 字节。表的分块因子为 bfr = (B/R) = 1024/204 = 5 每个磁盘块的记录。保存该表所需的块总数为 N = (r/bfr) = 5000000/5 = 1,000,000 块。

对 id 字段进行线性搜索平均需要 N/2 = 500,000 假设 id 字段是关键字段,则阻止访问以查找值。但由于 id 字段也是排序的,因此可以进行二分搜索,需要平均 log2 1000000 = 19.93 = 20 块访问。我们立即可以看到这是一个巨大的改进。

现在 字段既不是排序的也不是关键字段,因此不可能进行二分搜索,而且值也不是唯一的,因此表需要搜索到末尾以获取精确的值 N = 1,000,000 块访问。索引旨在纠正这种情况。

鉴于索引记录仅包含索引字段和指向原始记录的指针,因此它会比它指向的多字段记录小。因此,索引本身比原始表需要更少的磁盘块,因此需要更少的块访问来进行迭代。索引的架构 字段概述如下;

Field name       Data type      Size on disk
firstName        Char(50)       50 bytes
(record pointer) Special        4 bytes

笔记: :MySQL 中的指针长度为 2、3、4 或 5 个字节,具体取决于表的大小。

实施例2 - 索引

鉴于我们的样本数据库 r = 5,000,000 索引记录长度为的记录 R = 54 字节并使用默认块大小 B = 1,024 字节。索引的分块因子为 bfr = (B/R) = 1024/54 = 18 每个磁盘块的记录。保存索引所需的块总数为 N = (r/bfr) = 5000000/18 = 277,778 块。

现在使用以下搜索 字段可以利用索引来提高性能。这允许对索引进行二分搜索,平均为 log2 277778 = 18.08 = 19 块访问。为了找到实际记录的地址,这需要进一步的块访问来读取,使总数达到 19 + 1 = 20 块访问,与查找所需的 1,000,000 次块访问相去甚远 匹配非索引表。

什么时候应该使用它?

鉴于创建索引需要额外的磁盘空间(上例中额外增加了 277,778 个块,增加了约 28%),并且过多的索引可能会导致文件系统大小限制引起的问题,因此必须仔细考虑以选择正确的索引要索引的字段。

由于索引仅用于加快在记录中搜索匹配字段的速度,因此理所当然,仅用于输出的索引字段在执行插入或删除操作时只会浪费磁盘空间和处理时间,因此应该避免。另外,考虑到二分搜索的性质,数据的基数或唯一性也很重要。对基数为 2 的字段建立索引会将数据分成两半,而基数为 1,000 将返回大约 1,000 条记录。使用如此低的基数,效率会降低为线性排序,并且如果基数小于记录数的 30%,查询优化器将避免使用索引,从而实际上使索引浪费了空间。

其他提示

我第一次读到这篇文章对我来说非常有帮助。谢谢。

从那时起,我对创建索引的缺点有了一些认识:如果你写入一个表(UPDATE 或者 INSERT)使用一个索引,实际上在文件系统中有两次写入操作。一种用于表数据,另一种用于索引数据(及其排序(以及 - 如果是集群 - 表数据的排序))。如果表和索引位于同一硬盘上,则会花费更多时间。因此,没有索引(堆)的表将允许更快的写入操作。(如果您有两个索引,您最终将进行三个写入操作,依此类推)

然而,在两个不同的硬盘上为索引数据和表数据定义两个不同的位置可以减少/消除时间成本增加的问题。这需要定义附加文件组以及所需硬盘上的相应文件,并根据需要定义表/索引位置。

索引的另一个问题是随着数据的插入,它们会随着时间的推移而产生碎片。 REORGANIZE 有帮助,您必须编写例程来完成它。

在某些情况下,堆比带有索引的表更有帮助,

例如:- 如果您有很多竞争性的写作,但只有一篇每晚在工作时间外阅读以进行报告。

此外,聚集索引和非聚集索引之间的区别也相当重要。

帮助过我:- 聚集索引和非聚集索引实际上意味着什么?

索引只是一种数据结构,可以更快地搜索数据库中的特定列。该结构通常是 B 树或哈希表,但也可以是任何其他逻辑结构。

经典例子 《书籍索引》

考虑一本 1000 页的“书”,分为 100 个部分,每个部分有 X 页。

很简单吧?

现在,如果没有索引页,要查找以字母“S”开头的特定部分,除了扫描整本书之外,您别无选择。IE:1000页

但只要一开始就有索引页,你就可以了。而且,要阅读任何重要的特定部分,您只需每次都一次又一次地查看索引页。找到匹配的索引后,您可以通过跳过其他部分来有效地跳转到该部分。

但是,除了 1000 个页面之外,您还需要大约 10 个页面来显示索引页面,所以总共 1010 个页面。

因此,索引是一个单独的部分,它按排序顺序存储索引列的值+指向索引行的指针,以便进行高效查找。

学校里的事情很简单,不是吗?:P

现在,假设我们要运行一个查询来查找名为“Abc”的任何员工的所有详细信息?

SELECT * FROM Employee 
WHERE Employee_Name = 'Abc'

如果没有索引会发生什么?

数据库软件实际上必须查看 Employee 表中的每一行,以查看该行的 Employee_Name 是否为“Abc”。而且,因为我们希望每一行都包含名称为“Abc”的行,所以一旦找到名为“Abc”的行,我们就不能停止查找,因为可能还有其他行具有该名称 ABC. 。因此,必须搜索直到最后一行的每一行 - 这意味着在这种情况下,数据库必须检查数千行才能找到名称为“Abc”的行。这就是所谓的 全表扫描

数据库索引如何提高性能

拥有索引的全部目的是通过本质上减少表中需要检查的记录/行的数量来加速搜索查询。索引是一种数据结构(最常见的是 B 树),用于存储表中特定列的值。

B 树索引如何工作?

B 树之所以成为最流行的索引数据结构,是因为它们具有时间效率——因为查找、删除和插入都可以在对数时间内完成。而且,B 树更常用的另一个主要原因是 B 树中存储的数据可以排序。RDBMS 通常确定索引实际使用的数据结构。但是,在某些使用某些 RDBMS 的场景中,您实际上可以在创建索引本身时指定希望数据库使用哪种数据结构。

哈希表索引如何工作?

使用哈希索引的原因是哈希表在查找值时非常有效。因此,如果使用哈希索引,比较字符串是否相等的查询可以非常快速地检索值。

例如,我们之前讨论的查询可以受益于在 Employee_Name 列上创建的哈希索引。哈希索引的工作方式是,列值将成为哈希表的键,映射到该键的实际值将只是指向表中行数据的指针。由于哈希表基本上是一个关联数组,因此典型的条目看起来类似于“Abc => 0x28939”,其中 0x28939 是对存储在内存中的 Abc 的表行的引用。在哈希表索引中查找像“Abc”这样的值并获取对内存中该行的引用显然比扫描表以查找 Employee_Name 列中值为“Abc”的所有行要快得多。

哈希索引的缺点

哈希表不是排序的数据结构,并且有许多类型的查询哈希索引甚至无法提供帮助。例如,假设您想找出所有 40 岁以下的员工。如何使用哈希表索引做到这一点?嗯,这是不可能的,因为哈希表只适合查找键值对——这意味着检查相等性的查询

数据库索引到底包含什么?现在您知道数据库索引是在表中的列上创建的,并且该索引将值存储在该特定列中。但是,重要的是要了解数据库索引不会将值存储在同一表的其他列中。例如,如果我们在 Employee_Name 列上创建索引,这意味着 Employee_Age 和 Employee_Address 列值不会也存储在该索引中。如果我们只将所有其他列存储在索引中,那么就像创建整个表的另一个副本一样 - 这会占用太多空间并且效率非常低。

数据库如何知道何时使用索引?当运行“SELECT * FROM Employee WHERE Employee_Name = ‘Abc’”这样的查询时,数据库将检查正在查询的列上是否有索引。假设 Employee_Name 列确实创建了索引,数据库将必须决定使用索引来查找正在搜索的值是否真的有意义 - 因为在某些情况下使用数据库索引实际上效率较低,并且扫描整个表更高效。

拥有数据库索引的成本是多少?

它占用空间——表越大,索引就越大。索引对性能的另一个影响是,每当您在相应表中添加、删除或更新行时,都必须对索引执行相同的操作。请记住,索引需要包含与索引所覆盖的表列中的数据相同的最新数据。

作为一般规则,只有当索引列中的数据被频繁查询时才应在表上创建索引。

也可以看看

  1. 哪些列通常可以建立良好的索引?
  2. 数据库索引如何工作

简单描述!!!!!!!!!

索引只不过是存储表中特定列的值的数据结构。索引是在表的列上创建的。

例如,我们有一个名为 User 的数据库表,其中包含三列 – 姓名、年龄和地址。假设 User 表有数千行。

现在,假设我们要运行一个查询来查找名为“John”的任何用户的所有详细信息。如果我们运行以下查询。

SELECT * FROM User 
WHERE Name = 'John'

数据库软件实际上必须查看用户表中的每一行,以查看该行的名称是否为“John”。这将需要很长时间。
这就是索引帮助我们的地方“索引用于通过实质上减少表中需要检查的记录/行数来加速搜索查询”。
如何创建索引

CREATE INDEX name_index
ON User (Name)

索引由列值组成(例如:John)来自一个表,并且这些值存储在数据结构中。
因此,现在数据库将使用索引来查找名为 John 的员工,因为索引可能会按用户名的字母顺序排序。而且,因为它是排序的,这意味着搜索名称要快得多,因为所有以“J”开头的名称将在索引中彼此相邻!

只是一个快速建议..由于索引会消耗额外的写入和存储空间,因此如果您的应用程序需要更多插入/更新操作,您可能需要使用没有索引的表,但如果需要更多数据检索操作,您应该使用索引表。

只需将数据库索引视为一本书的索引即可。如果您有一本关于狗的书,并且想要查找有关德国牧羊犬的信息,您当然可以翻阅该书的所有页面并找到您要查找的内容,但这当然很耗时而且不是很快速地。另一种选择是,您可以转到本书的索引部分,然后使用您正在查找的实体的名称(在本例中为德国牧羊犬)并查看页码来查找您要查找的内容。快速找到您要找的东西。在数据库中,页号被称为指针,它将数据库定向到实体所在磁盘上的地址。使用相同的德国牧羊犬类比,我们可以得到类似的内容(“德国牧羊犬”,0x77129),其中 0x77129 是磁盘上存储德国牧羊犬行数据的地址。

简而言之,索引是一种存储表中特定列的值以加快查询搜索的数据结构。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top