数据库之索引

在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

没有建立索引的时候,我们对表的查询需要MySQL全表扫描来查找数据,如果这张表记录很多,效率无疑是很低下的。使用索引就可以在索引中查找符合条件的索引值,然后快速找到表中对应的记录。

MySQL的索引分为普通索引、唯一索引、主键索引、全文索引和组合索引。

普通索引

普通索引是最基本的索引,没有任何限制。

创建普通索引的SQL语句形式如下:

CREATE INDEX 索引名称 ON 表名(属性名(length));

还可以使用alter语句修改表结构的方法增加索引:

ALTER TABLE 表名 ADD INDEX 索引名 ON (属性名(length));

也可以在创建表时就添加索引:

CREATE TABLE student(
    id INT(11) PRIMATY KEY,
    name VARCHAR(20) NOT NULL,
    sex VARCHAR(10) NOT NULL,
    INDEX 索引名(属性名(length))
)

以上三种方式中属性名的length参数一般小于指定属性的实际长度。当索引很长时会很占内存,这是可以选择只取字符串的前几个字符作为索引,这种索引称为前缀索引。此处的length就是指定使用字符串的前length个字符作为索引。

删除普通索引的SQL语句形式如下:

DROP INDEX 索引名称 ON 表名;

唯一索引

唯一索引与普通索引类似,区别是索引列的值必须唯一,允许有空值。如果是组合索引,则列值的组合必须唯一。

创建唯一索引的SQL语句形式如下:

CREATE UNIQUE INDEX 索引名 ON 表名(属性名(length));

使用alter语句修改表结构增加索引SQL语句形式如下:

ALTER TABLE ADD UNIQUE 索引名 ON (属性名(length));

同样也可以在创建表的时候指定唯一索引:

CREATE TABLE student(
    id INT(11) PRIMATY KEY,
    name VARCHAR(20) NOT NULL,
    sex VARCHAR(10) NOT NULL,
    UNIQUE 索引名(属性名(length))
)

主键索引

主键索引就是我们创建表的时候指定主键的primary key语句,一个表只能有一个主键索引,且不能有空值。

全文索引

全文索引主要用于全文检索,但只能在类型为char、varchar或text的属性上。

创建全文索引的SQL语句形式如下:

CREATE FULLTEXT INDEX 索引名称 ON 表名(属性名);

使用alter语句修改表结构添加全文索引SQL语句形式如下:

ALTER TABLE ADD FULLTEXT INDEX 索引名称(属性名);

创建表时指定全文索引:

CREATE TABLE student(
    id INT(11) PRIMATY KEY,
    name VARCHAR(20) NOT NULL,
    sex VARCHAR(10) NOT NULL,
    FULLTEXT KEY 索引名(属性名)
)

全文索引在使用时有自己的语法结构,使用match和against查找,其使用SQL语句形式如下:

SELECT 属性列表 FROM 表名
WHERE MATCH(全文索引指定的列) AGAINST('检索内容');

需要注意的是,match中的列必须与全文索引中的列完全相同,否则不能使用全文索引。

组合索引

索引列多于一列的索引就叫做组合索引。建立组合索引就相当于建立了多个索引,例如组合索引composite_index(a,b,c)相当于a,ab,abc三个索引。并且MySQL每次只能使用一个索引,索引列越多,筛选出的数据项就越少。

创建组合索引的SQL语句形式如下:

CREATE INDEX 索引名称 ON 表名(属性1,属性2,...);

使用alter语句创建组合索引SQL语句如下:

ALTER TABLE 表名 ADD INDEX 索引名称(属性1,属性2,...);

最左匹配原则

最左匹配原则主要针对组合索引,指在匹配数据时从最左侧开始匹配,一直向右匹配直到遇到<、>、between和like就停止匹配。因此,我们在建立组合索引时应按照查询频率由高到低的顺序将索引列从左到右排列。

例如组合索引composite_index(a,b,c),在查询时使用类似如下查询语句便可触发该索引:

SELECT * FROM table WHERE a = '';
SELECT * FROM table WHERE a = '' AND b = '';
SELECT * FROM table WHERE a = '' AND b = '' AND c = '';

事实上使用ac组合同样可以触发该索引,只是只会用到a列索引,不会用到c列。而abc的任意顺序组合也可以用到abc三列的索引,类似的,ba组合同样可以使用到ab列索引。

为方便举例,创建city表如下:

city(city_id,city_name,province_id,first_letter,is_hot,state)

在city表上建立组合索引如下:

ALTER TABLE city ADD INDEX composite_index (city_id,city_name,province_id);

首先我们先测试city_id,city_name和province_id的顺序是否触发索引:

EXPLAIN SELECT * FROM city WHERE city_id = 130201 AND city_name = '唐山市' AND province_id = '130000';

输出结果如下:

查看possible_keys可以看出来触发了composite_index索引。

然后我们尝试province_id,city_name和city_id的顺序是否可以触发:

EXPLAIN SELECT * FROM city WHERE province_id = '130000' AND city_name = '唐山市' AND city_id = 130201;

输出结果如下:

可以看到同样是触发了的,原因在于MySQL查询优化器会判断这条SQL语句以怎样的顺序执行效率更高从而去纠正,也就是说最终执行的顺序还是索引顺序city_id、city_name和province_id。

我们再来看看跳过city_id,使用city_name和province_id的顺序是否会触发:

EXPLAIN SELECT * FROM city WHERE city_name = '唐山市' AND province_id = '130000';

输出结果:

很明显,没有触发索引。

而对于范围查询,例如索引composite_index(a,b,c),查询语句:

SELECT * FROM table
WHERE a = 1 AND b < 10 AND c = 1;

只会用到ab列的索引,因为c列的索引此时是无序的。

索引优化

合理的创建索引和使用索引可以让提交检索效率,增加触发索引几率。索引优化的方法如下:

  1. 较频繁的作为查询条件的字段应该创建索引。
  2. 唯一性太差的字段不适合创建索引,如果不能有效的区分数据,这个列即便查询再频繁也不应该创建索引。
  3. 不会出现在where子句中的属性不应该创建索引。
  4. 尽量不要使用like语句,如果一定要使用,尽量不让通配符在前面,因为'%aa'不会使用索引,而'bb%'会使用。
  5. 索引列尽量设置成非空,复合索引中有一列包含null值,这一列对于复合索引就是无效的。
  6. 不要在索引列上计算,会导致索引失效,全表扫描。
  7. 不使用not in、!=和<>操作,会使引擎放弃索引而使用全表扫描。
  8. 少用or,其前后只要有一个列没有索引,都会导致引擎放弃索引使用全表扫描。
  9. 使用短索引,可以通过指定前缀长度来使用短索引,短索引可以增加查询速度且减少I/O操作。

你可能感兴趣的:(数据库)