索引如何使数据库更快
多数人问为什么与平面文件输入数据相比,数据库这么快?
这背后有许多原因,其中之一就是索引。
当然,底层磁盘子系统的速度在提高数据库速度方面也起着重要作用。
由于几乎所有使用重型数据库的都大量使用关系数据库,因此了解数据库的内部工作变得非常重要,或者我必须说出哪些因素使数据库在性能方面变得高效。
在进入数据库索引之前,让我们先回顾一些计算机基础知识。
计算机硬盘和存储设备的最新发展已导致读写操作的速度和性能提高。
但是,像内存这样的易失性存储设备可使更快的读写操作更加无缝。
由于这个原因,计算机操作系统的设计方式是永远不会直接从机械设备(例如硬盘设备)中获取数据,而是首先将数据从硬盘传输到速度更快的设备(例如内存(volatile))中,从那里应用程序和其他程序直接按需获取数据。
不同的数据库引擎使用不同的策略来存储和检索数据。
我们将从理解硬盘,内存和页面背后的思想开始本教程,因为几乎所有数据库都不可避免地会以某种方式使用它们。
硬盘有时被称为辅助存储设备,存储在硬盘中的数据将在系统重新引导后保持不变。
让我们看看硬盘的内部外观。
从内存读取数据是瞬时的。
数据从硬盘传输到内存,再从内存传输回硬盘的过程由操作系统完成。
实际上,诸如数据库之类的应用程序借助于操作系统提供的缓冲区管理API来利用此过程。
我们已经看到了从硬盘的不同扇区获取数据所涉及的开销。
但是,如果将数据分散在连续的扇区(一个接一个)上,那么它将改善获取数据的性能。
由于主轴和主轴头不需要移动/旋转,因此可以从一个接一个的扇区获取数据。
为了提高性能,数据库服务器始终可以要求操作系统将数据排在另一个块之后。
MySQL中的“ OPTIMIZE TABLE”对特定的表执行相同的操作。
在运行该命令时,操作系统将一个表中的记录依次排列。
此过程有时也称为碎片整理。
碎片整理将改善以下方面。
- 硬盘查找时间减少(因为可以从相邻扇区获得数据)
- 主轴旋转的等待时间
- 资料撷取时间
数据库中的索引如何使它的操作更快?
让我举一个例子。
假设我们在商店里购买有关TCP/IP的书。
我们找到了一本合适的书,其中包含与TCP/IP相关的所有信息。
店主永远不会让我们坐在那里阅读整本书!!因此,我们大多数人所做的就是在那本书中搜索我们感兴趣的主题。
我们将如何从一本包含1000页的TCP/IP书籍中搜索我们感兴趣的主题。
如果我们坐在那里并一页一页地翻页,请确保店主一定会在一段时间内拍打背。
这是作者实施“目录”或者有时称为“索引”的主要原因。
大多数书籍的开头确实保留了几页供Index使用。
我们可以轻松地从目录中搜索我们感兴趣的主题,并直接找到该主题的确切页码。
数据库索引在某种程度上类似于本书中的目录。
索引将有助于快速检索数据库查询(因为该查询不需要遍历整个表来获取数据,但是会从索引中找到数据块。
)。
让我们深入了解数据库表的一些基础知识。
从上面显示的示例数据库表中,我们可以清楚地了解什么是记录和什么是字段。
假设上面的数据库很大,有10万记录,这意味着每个提交的数据库都将有10万的值。
现在,如果我想从这10万个字段中进行搜索,那么线性搜索将花费很长时间才能完成,但是对于二进制搜索呢(二进制搜索是一种快速搜索算法,当我们有一个排序的值列表时,或者升序或者降序。
)
想象一下,我们在上述数据库中使用了固定长度的记录(这意味着所有记录的大小都是固定的。
)因此,假设记录长度为204字节(这仅是为了简化计算)。
并假设我们的默认块大小为1024字节。
因此,我们有以下内容。
固定记录大小= 204字节
块大小= 1024字节
因此每块记录= 1024/204 = 5条记录
在上面的示例中,我们以10万条记录为例,因此..
1十万/5 =20000。
因此,对于1万条记录,我们需要20000块。
因此,如果我们进行线性搜索,则需要搜索20000个块以查找归档的项目。
但是,如果执行二进制搜索,则“ 20000的对数基数为14.287712”。
这意味着我们只需要遍历排序的值14次,即可使用二进制搜索找到我们感兴趣的唯一值。
为表中的任何字段创建索引(在表中创建唯一值字段的索引是一种最佳方法,因为该字段可用于检索其他字段。
)将创建另一个包含该字段的排序值的表。
但是,话虽如此,表中所有字段的索引较大,也会导致性能下降。
想象一下,如果索引与一个表一样长,那么再次浏览将是一项开销。
要记住的另一件重要事情是,建立索引将提高查询的读取性能,同时会降低写入性能。
因为如果我们更改或者更改记录,或者说在数据库中添加新条目,它将执行两次写操作(一个操作将自己写记录,另一个操作将更新索引)。
因此,在编制索引时必须牢记以下几点。
- 索引表中的每个字段都会降低写入性能。
- 建议在表中为具有唯一值的字段建立索引
- 必须索引在关系数据库中充当联接的字段,因为它们有助于跨多个表的复杂查询。
- 索引还使用磁盘空间,因此在选择要索引的字段时要小心
如何为字段创建索引?
让我们为如下所示的学生示例数据库创建索引。
mysql> select * from students; +------+--------+----------+ | stno | stname | courseid | +------+--------+----------+ | 301 | David | 20 | | 302 | Justin | 30 | | 303 | John | 20 | | 304 | Mark | 40 | | 305 | Joseph | 30 | | 306 | Martin | 40 | | 307 | James | 30 | +------+--------+----------+ 7 rows in set (0.00 sec)
尽管该表对于创建索引来说并不大,但是为了显示该示例索引创建示例,让我们为“ stno”字段创建索引。
mysql> CREATE INDEX id_index ON students (stno) USING BTREE; Query OK, 7 rows affected (0.11 sec) Records: 7 Duplicates: 0 Warnings: 0
让我们看一下我们刚刚创建的该索引的内容。
mysql> show index from students; +----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | +----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | students | 1 | id_index | 1 | stno | A | NULL | NULL | NULL | YES | BTREE | | +----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 1 row in set (0.00 sec) mysql>
有关数据库索引的注意事项
- 数据库中的索引仅包含排序的值,因此,在字段中搜索特定值变得更快
- 二进制搜索算法用于从索引中搜索,从而使搜索速度更快
- 包含联接的数据库查询通过索引变得更快
- 可以通过在数据库中建立索引来减少磁盘输入输出操作
- 如果假设存在一个仅从索引字段中检索数据的查询,则数据库服务器将仅访问索引而不访问该行中的完整数据。
- 索引表中的大量字段会使写入操作变慢