数据库索引

    索引可以使mysql快速的找到和检索一张包含百万甚至亿万数据的表中的一组纪录。如果你曾使用过mysql,不管是多久,你可能为了更轻快的得到查询的结果而使用过索引。你也可能发现mysql的索引有时候并不想你想像的那样工作。

    对很多使用者来说,索引就像黑色的艺术。有时候奇迹快速地工作,有时候却像是缓慢或者阻碍数据插入。

    在本章中,我们将介绍一些索引的概念和mysql提供的各种不同索引。

    理解mysql如何使用索引,最好首先理解索引的基础工作和特征。一旦你对索引的特征有基本的理解,你就能够更加合理的正确使用它们了。

    要理解索引让mysql做什么,思考mysql是如何工作才得到查询的结果。想象电话本是一个含有California州大约35000000条电话的电话本集合。无序地记录在大脑里,考虑这样查询:

select * from phone_book where last_name='Zawodny';

    没有任何类型的索引来咨询,数据库必须读在phone_book这张表里的所有记录,然后比较last_name这个字段是否与字符串"Zawodny"匹配上。当然了,这种方法是低效的。一旦电话的记录增加了,就会需要去找对应给予的记录。在计算机科学中,我们称之为O(n)时间复杂度问题。

    然而给定的真实电话本,我们都知道如何快速定位到名字是Zawodny的地方:翻到书的后面,以Z开头的地方。因为第二个单词是a,我们知道所有匹配的会在名单列表以Z开头的未知附近。这个方法是基于数据排序的知识的。

    这是作弊,不是吗?并不是。你可以快速找到Zawodnys的原因是它们的姓被按字母排序了。当然了,如此简单的找到Zawodny是因为你知道ABC字母。。。

    多数教科书(比如这本)都会在数的背面提供索引。因为这些索引按顺序排列在相应的页码,使你经常快速的找到书中的术语和概念。想要知道数据库热拷贝在哪里有讨论吗?查看索引页久知道了。

    数据库索引也是类似的。书的作者或出版者将会在书中选择重要的概念和术语作为索引。你可以在数据库的表中选择特定的字段创建索引。用前面的例子,你会创建姓为索引来快速查找电话号码:

ALTER TABLE phone_book ADD INDEX (last_name)

    在这样做的过程中,你会在phone_book表中向数据库要一个按姓排列的顺序列表。每个名字都有自己匹配记录的位置--就像这本书后面索引中列的各个条目的页码。

    从数据库服务器的角度来看,当在执行一个查询时索引的存在可以从固定的结果中快速的删除可能的行。在没有任何索引时,MYSQL(比如一个数据库服务器)会检查表中的每一行数据。这不仅仅是时间上的浪费,也会占用大量磁盘输入输出从而严重弄脏磁盘缓存。

    在真实世界中,很少能找到刚刚被排序和已经排序的动态的数据。书是一种特例,它们趋向于保持静止。

    因为数据库需要为索引值维护一个单独的列表,并在数据更新同时使它们保持更新。你千万不能希望一个表中的所有字段都作为索引。索引是一种空间和时间的折中。在做每个insert,update,delete查询时使你的大部分(不是全部)查询更快时,你将在磁盘空间和CPU上牺牲一些额外的空间。

    大部分数据库的说明书使用了术语索引和键可互换。说last_name是phone_book表中的一个键等同于last_name字段是phone_book表的索引。

    索引是空间和性能的交换。但是有时候你并不希望用空间来交换性能。幸亏,MYSQL为你提供了很多关于通过索引控制空间的方法。当你有一张phone_book表,里面有二十亿数据。在last_name上增加一个索引将需要很多空间,如果每个last_name占8位,你会发现这个数据的索引大约需要16G的空间。无论你要做什么,行指针都要对每条记录增加额外的4-8位。

    你可以只将前4位作为索引,而不是将整个last name作为索引。

ALERT TABLE phone_book ADD INDEX (last_name(4))

    当你这样做的时候,已经减少了索引所需要部分数据约一半的空间。这个折中的是MYSQL不能消除太多行使用这个索引。比如像下面这样的查询:

数据库索引