索引是用来加快从数据库中查询数据的速度的。

需要注意的是索引的使用会增加插入和更新的时间,因为在插入数据的同时也会更新索引。所以在创建索引时确保只在那些频繁作为查询条件的列中增加。

创建索引

创建索引时有几个需要注意的点:

不要在频繁写,而读取频率较低的表上使用索引,和之前说的那样,索引提高了读速度,而损耗了写速度

不要在 low cardinality 的列上使用索引,Cardinality 直接翻译是基数,可以理解成为这一列取值的散列程度,如果一个列包含的值只有少数几个,那么索引的效果也无法达到

不要在固定大小的表上使用索引,小数量集的表增加索引并不会带来多大的性能提升,所以尤其需要注意的是那些可能随着时间数据量增长很快的表,比如 users 表

在建表时

CREATE INDEX idx_name ON table_name(column1, column2);

ALTER TABLE `table_name` ADD INDEX idx_name (`column1`);

创建唯一索引

ALTER TABLE `table_name` ADD UNIQUE uni_name (`column1`)

显示查看索引

查看表索引

SHOW INDEX FROM table_name;

在查询的结果中可以看到索引的名字,列名,散列程度(Cardinality),索引类型(BTREE) 等等。

查询 Schema 中所有的索引

SELECT DISTINCT

TABLE_NAME,

INDEX_NAME

FROM INFORMATION_SCHEMA.STATISTICS

WHERE TABLE_SCHEMA = 'your_schema';

删除索引

DROP INDEX idx_name ON table_name;

ALTER TABLE table_name DROP INDEX idx_name;

Single index vs Composite index

组合索引和单一索引一样,不过组合索引是需要组合多列。

假设有用户表 users

ID | first_name | last_name | class | position |

--------------------------------------------------------

1 | Teemo | Shroomer | Specialist | Top |

2 | Cecil | Heimerdinger | Specialist | Mid |

3 | Annie | Hastur | Mage | Mid |

4 | Fiora | Laurent | Slayer | Top |

5 | Garen | Crownguard | Fighter | Top |

然后在 class 和 position 列上创建组合索引

CREATE INDEX class_pos_index ON users (class, position);

然后数据库会创建一个组合索引的排序,类似:

class-position Primary Key

--------------------------------

AssassinMid -> 10

ControllerSupport -> 16

ControllerSupport -> 18

ControllerSupport -> 8

FigherTop -> 7

FigherTop -> 9

FighterJungle -> 13

FighterJungle -> 21

FighterJungle -> 23

假设需要查询班级中的 Top,那么会提升速度:

SELECT * FROM users

WHERE

class = 'Specialist'

AND

position = 'Top';

因为按照了 class-position 来排序,所以查询速度得到了提升。数据库能够在 O(log_2(n)) 时间内查找到 Specialist-Top 而不需要读取全表。

需要注意的是即使查询条件只有 class 字段,组合索引依然能够提升速度,因为class 在组合索引的第一个位置。

但是单纯的查询 position

SELECT * FROM users WHERE position = 'Top';

则享受不到组合索引带来的好处。所以组合索引的列顺序非常关键。

创建组合索引的一些注意点:

如果特定列固定的出现在查询条件中,那么对这些列创建组合索引比较好

如果要创建 field1 上的索引,也要创建 (field1, field2) 上的索引,那么只创建一个组合索引 (field1, field2) 已经足够

和 Single indexes 一样,组合索引的 Cardinality 一样重要。显然当两个 field 有高的 Cardinality,组合索引的 Cardinality 也会很高。但是某一些情况下低 Cardinality 的列也会有高的 Cardinality 组合索引

reference