mysql索引太大怎么办 mysql索引坏处( 三 )


假设我们创建了一个名为people的表:
CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );
然后,我们完全随机把1000个不同name值插入到people表 。下图显示了people表所在数据文件的一小部分:
可以看到 , 在数据文件中name列没有任何明确的次序 。如果我们创建了name列的索引,MySQL将在索引中排序name列:
对于索引中的每一项,MySQL在内部为它保存一个数据文件中实际记录所在位置的“指针” 。因此,如果我们要查找name等于“Mike”记录的peopleid(SQL命令为“SELECT peopleid FROM people WHERE name=\'Mike\';”) , MySQL能够在name的索引中查找“Mike”值,然后直接转到数据文件中相应的行 , 准确地返回该行的peopleid(999) 。在这个过程中 , MySQL只需处理一个行就可以返回结果 。如果没有“name”列的索引,MySQL要扫描数据文件中的所有记录,即1000个记录!显然,需要MySQL处理的记录数量越少,则它完成任务的速度就越快 。
二、索引的类型
MySQL提供多种索引类型供选择:
普通索引
这是最基本的索引类型,而且它没有唯一性之类的限制 。普通索引可以通过以下几种方式创建:
创建索引,例如CREATE INDEX 索引的名字 ON tablename (列的列表);
修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);
创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) );
唯一性索引
这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一 。唯一性索引可以用以下几种方式创建:
创建索引,例如CREATE UNIQUE INDEX 索引的名字 ON tablename (列的列表);
修改表 , 例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表);
创建表的时候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) );
主键
主键是一种唯一性索引,但它必须指定为“PRIMARY KEY” 。如果你曾经用过AUTO_INCREMENT类型的列,你可能已经熟悉主键之类的概念了 。主键一般在创建表的时候指定,例如“CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); ” 。但是,我们也可以通过修改表的方式加入主键,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ” 。每个表只能有一个主键 。
全文索引
MySQL从3.23.23版开始支持全文索引和全文检索 。在MySQL中,全文索引的索引类型为FULLTEXT 。全文索引可以在VARCHAR或者TEXT类型的列上创建 。它可以通过CREATE TABLE命令创建,也可以通过ALTER TABLE或CREATE INDEX命令创建 。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快 。本文下面的讨论不再涉及全文索引,要了解更多信息,请参见MySQL documentation 。
三、单列索引与多列索引
索引可以是单列索引,也可以是多列索引 。下面我们通过具体的例子来说明这两种索引的区别 。假设有这样一个people表:
ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);
由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname , 然后再转到合适的lastname,最后转到合适的age 。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录!
那么,如果在firstname、lastname、age这三个列上分别创建单列索引 , 效果是否和创建一个firstname、lastname、age的多列索引一样呢?答案是否定的,两者完全不同 。当我们执行查询的时候,MySQL只能使用一个索引 。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引 。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引 。

推荐阅读