索引的作用
加快数据查询速度
什么是索引?
索引是帮助MySQL高效获取数据的数据结构
索引在存储引擎中实现,每种存储引擎的索引都不一定完全相同,每种存储引擎也不一定支持所有的所有类型
索引的分类
普通索引和唯一索引
普通索引是MySQL的基本索引类型
唯一索引对应列的值必须唯一,但允许空值。如果是组合索引,则列值的组合必须唯一
主键索引是一种特殊的唯一索引,不允许有空值
单列索引和组合索引
单列索引指只包含一个列的索引。一个表中可以有多个单列索引
组合索引指表的多个字段组合上创建的索引。遵循做前缀集合
全文索引
FULLTEXT类型索引。可以在CHAR,VARCHAR或者TEXT类型的列上创建
仅MYISAM支持
空间索引
对空间数据类型的字段建立的索引
索引设计原则
索引并非越多越好
数据量不多不需要建立索引
列中的值变化不多也不需要建立索引
经常排序和分组的数据列要建立索引
唯一性约束对应使用唯一性索引
创建索引
在建表的同时,创建索引
创建普通索引
CREATE TABLE t1( id,INT PRIMARY KEY, name varchar(10), sex ENUM('F','M','UN'), INDEX(name) )ENGINE=MYISAM CHARACTER SET utf8; |
mysql> create table t_1 (id int, name varchar(10), index(name)); Query OK, 0 rows affected (0.32 sec) mysql> show create table t_1\G; *************************** 1. row *************************** Table: t_1 Create Table: CREATE TABLE `t_1` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
创建唯一索引
UNIQUE INDEX
CREATE TABLE t2 ( id INT NOT NULL, name varchar(10), sex ENUM('F','M','UN'), UNIQUE INDEX 'id_in' ( 'id' ) )ENGINE=MYISAM CHARACTER SET utf8; |
mysql> create table t_2 ( -> id int, -> name varchar(10), -> unique index idInx (id) -> ); Query OK, 0 rows affected (0.06 sec) mysql> show create table t_2\G; *************************** 1. row *************************** Table: t_2 Create Table: CREATE TABLE `t_2` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, UNIQUE KEY `idInx` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
创建单列索引
CREATE TABLE t1 ( id INT PRIMARY KEY, name varchar(20), sex ENUM('F','M','UN'), INDEX 'name_index' ( 'name' (10) ) )ENGINE=MYISAM CHARACTER SET utf8; |
mysql> create table t_3 ( -> id int, -> name varchar(10), -> index idinx (name(10)) -> ); Query OK, 0 rows affected (0.02 sec) mysql> show create table t_3\G; *************************** 1. row *************************** Table: t_3 Create Table: CREATE TABLE `t_3` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, KEY `idinx` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
创建组合索引
CREATE TABLE t1 ( id INT NOT NULL, name varchar(20), age INT NOT NULL, INDEX 'Multi_in' (id,name,age(100)) )ENGINE=MYISAM CHARACTER SET utf8; |
mysql> create table t_4 ( -> id int, -> name varchar(10), -> age int, -> index MutilIdx (id,name,age) -> ); Query OK, 0 rows affected (0.09 sec) mysql> show create table t_4\G; *************************** 1. row *************************** Table: t_4 Create Table: CREATE TABLE `t_4` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, `age` int(11) DEFAULT NULL, KEY `MutilIdx` (`id`,`name`,`age`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
mysql> insert into t_4 values(1,'AAA','10'),(2,'BBB','20'),(3,'CCC','30'),(4,'DDD','40'),(5,'EEE','50'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql> select * from t_4; +------+------+------+ | id | name | age | +------+------+------+ | 1 | AAA | 10 | | 2 | BBB | 20 | | 3 | CCC | 30 | | 4 | DDD | 40 | | 5 | EEE | 50 | +------+------+------+ 5 rows in set (0.00 sec) mysql> explain select name,age from t_4 where id<3; +----+-------------+-------+-------+---------------+----------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+----------+---------+------+------+--------------------------+ | 1 | SIMPLE | t_4 | index | MutilIdx | MutilIdx | 43 | NULL | 5 | Using where; Using index | +----+-------------+-------+-------+---------------+----------+---------+------+------+--------------------------+ 1 row in set (0.04 sec) mysql> explain select name,age from t_4 where id<3\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t_4 type: index possible_keys: MutilIdx key: MutilIdx key_len: 43 ref: NULL rows: 5 Extra: Using where; Using index 1 row in set (0.00 sec) ERROR: No query specified
创建全文索引
CREATE TABLE t1 ( id INT NOT NULL, name varchar(20), age INT NOT NULL, info TEXT, FULLTEXT INDEX 'info_in' (info) )ENGINE=MYISAM CHARACTER SET utf8; |
修改和删除索引
索引管理
使用ALTER语句
ALTER TABLE t1 ADD INDEX nameIndex (name(20)); ALTER TABLE t1 DROP INDEX nameIndex; |
mysql> show create table t_5\G; *************************** 1. row *************************** Table: t_5 Create Table: CREATE TABLE `t_5` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified mysql> alter table t_5 add index nameIdx (name); Query OK, 0 rows affected (0.08 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table t_5\G; *************************** 1. row *************************** Table: t_5 Create Table: CREATE TABLE `t_5` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, KEY `nameIdx` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
增加
mysql> alter table t_5 add unique index nameIdx1 (name); Query OK, 0 rows affected (0.07 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table t_5\G; *************************** 1. row *************************** Table: t_5 Create Table: CREATE TABLE `t_5` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, UNIQUE KEY `nameIdx1` (`name`), KEY `nameIdx` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
删除
mysql> alter table t_5 drop index nameIdx; Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table t_5\G; *************************** 1. row *************************** Table: t_5 Create Table: CREATE TABLE `t_5` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, UNIQUE KEY `nameIdx1` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
使用CREATE语句
CREATE INDEX nameIdx ON t1(name); |
mysql> create index idIdx on t_5(id); Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table t_5\G; *************************** 1. row *************************** Table: t_5 Create Table: CREATE TABLE `t_5` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, UNIQUE KEY `nameIdx1` (`name`), KEY `idIdx` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
使用DROP语句
DROP INDEX 'name_index' ON t1; |
mysql> drop index idIdx on t_5; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table t_5\G; *************************** 1. row *************************** Table: t_5 Create Table: CREATE TABLE `t_5` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, UNIQUE KEY `nameIdx1` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) ERROR: No query specified
索引性能测试
1、准备环境
在数据库中创建测试表
CREATE TABLE test1 ( id int' num int, pass varchar(50) ); |
在系统提示符下执行如下语句创建100万行数据
for ((i=1;i<=1000000;i++));do `mysql -uroot -predhat db1 -e "insert into test1 values ($i,floor($i+rand()*$i),md5($i))"`;done |
2、简单测试索引性能
分别在有索引和没有索引的情况下执行查询。
分别在有索引和没有索引的情况下新增数据。
mysql> desc test1; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | num | int(11) | YES | | NULL | | | pass | varchar(50) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.05 sec)
1、使用limit查询指定的行数
mysql> select * from test1 limit 10; +------+------+----------------------------------+ | id | num | pass | +------+------+----------------------------------+ | 1 | 1 | c4ca4238a0b923820dcc509a6f75849b | | 2 | 2 | c81e728d9d4c2f636f067f89cc14862c | | 3 | 4 | eccbc87e4b5ce2fe28308fd9f2a7baf3 | | 4 | 4 | a87ff679a2f3e71d9181a67b7542122c | | 5 | 8 | e4da3b7fbbce2345d7772b0674a318d5 | | 6 | 9 | 1679091c5a880faf6fb5e6087eb1b2dc | | 7 | 9 | 8f14e45fceea167a5a36dedd4bea2543 | | 8 | 12 | c9f0f895fb98ab9159f51fd0297e236d | | 9 | 16 | 45c48cce2e2d7fbdea1afc51c7c6ad26 | | 10 | 10 | d3d9446802a44259755d38e6d163e820 | +------+------+----------------------------------+ 10 rows in set (0.00 sec) |
2、刷新查询缓存
mysql> reset query cache; Query OK, 0 rows affected (0.00 sec) |
3、测试查询
mysql> select num,pass from test1 where id>50000 and id<50050; ...... | 58801 | ce9e053a63f6a8aed199bed09f1e498e | |
4、创建test2并且添加索引
mysql> create table test2 ( -> id int, -> num int, -> pass varchar(50), -> index idIdx (id) -> ); Query OK, 0 rows affected (0.10 sec) mysql> insert into test2 select * from test1; Query OK, 184893 rows affected (4.64 sec) Records: 184893 Duplicates: 0 Warnings: 0 |
测试查询
mysql> select num,pass from test2 where id>50000 and id<50050; ...... | 70925 | 3b4421d0ab0e43c65932c51fb58f593f | |
5、不使用索引创建表、插入数据(比添加索引消耗的时间短)
mysql> create table test3( -> id int, -> num int, -> pass varchar(50) -> ); Query OK, 0 rows affected (0.06 sec) mysql> reset query cache; Query OK, 0 rows affected (0.00 sec) mysql> insert into test3 select * from test1; Query OK, 184893 rows affected (3.37 sec) Records: 184893 Duplicates: 0 Warnings: 0 |
总结
索引从本质上讲是一种数据结构
记住索引的设计原则
FULLTEXT索引仅能在MYISAM上使用
数据量巨大的表要慎重操作索引
索引的管理可以使用多种不同的方法