索引
一, 索引的介绍
数据库中专门用于帮助用户快速查找数据的一种数据结构. 类似于字典中的目录, 查找字典内容时可以根据目录查找到数据的存放位置吗, 然后直接获取.
二 , 索引的作用
约束和加速查找
三, 常见的几种索引:
普通索引, 唯一索引, 主键索引(这几个都是单列)
联合索引(多列), 比如: 联合主键索引, 联合唯一索引, 联合普通索引
无索引和有索引的区别以及建立索引的目的
无索引: 从前往后一条一条查询
有索引: 创建索引的本质, 就是创建额外的文件(某种格式存储, 查询的时候, 先去格外的文件找, 定好位置, 然后再去原始表中直接查询. 但是创建索引越多, 会对硬盘也是有损耗.
建立索引的目的:
a. 额外的文件保存特殊的数据结构
b. 查询快, 但是插入更新删除依然慢
c. 创建索引之后, 必须命中索引才能有效
索引的种类
hash 索引和 BTree 索引
(1)hash 类型的索引: 查询单条快, 范围查询慢
(2)btree 类型的索引: b + 树, 层数越多, 数据量指数级增长(我们就用它, 因为 innodb 默认支持它)
3.1 普通索引
作用: 仅有一个加速查找
创建表 + 普通索引
- create table userinfo(
- nid int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- index ix_name(name) ### 这里是索引
- );
普通索引
create index 索引的名字 on 表名(列名)
删除索引
drop index 索引的名字 on 表名
查看索引
show index from 表名
3.2 唯一索引
唯一索引有两个功能: 加速查找和唯一约束(可含 null)
创建表 + 唯一索引
- create table userinfo(
- id int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- unique index ix_name(name) ### 这里是索引
- );
唯一索引
create unique index 索引名 on 表名(列名)
删除唯一索引
drop unique index 索引名 on 表名
3.3 主键索引
主键索引有两个功能: 加速查找和唯一约束(不含 null)
创建表 + 主键索引
- create table userinfo(
- id int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- unique index ix_name(name)
- );
或者
- create table userinfo(
- id int not null auto_increment,
- name varchar(32) not null,
- email varchar(64) not null,
- primary key(nid),
- unique index ix_name(name)
- );
主键索引
alter table 表名 add primary key(列名);
删除主键索引
alter table 表名 drop primary key;
alter table 表名 modify 列名 int, drop primary key;
3.4 组合索引
组合索引是将 n 个列组合成一个索引
其应用场景为: 频繁的同时使用 n 列来进行查询, 如: where name = 'alex' and email = 'alex@qq.com'.
create index 索引名 on 表名(列名 1, 列名 2);
主键索引
alter table 表名 add primary key(列名);
删除主键索引
alter table 表名 drop primary key;
alter table 表名 modify 列名 int, drop primary key;
3.4 组合索引
组合索引是将 n 个列组合成一个索引
其应用场景为: 频繁的同时使用 n 列来进行查询, 如: where name = 'alex' and email = 'alex@qq.com'.
create index 索引名 on 表名(列名 1, 列名 2);
四, 索引名词
# 覆盖索引: 在索引文件中直接获取数据
例如:
- select name from userinfo where name = 'alex50000';
- # 索引合并: 把多个单列索引合并成使用
例如:
select * from userinfo where name = 'alex13131' and id = 13131;
五, 正确使用索引的情况
数据库表中添加索引后确实会让查询速度起飞, 但前提必须是正确的使用索引来查询, 如果以错误的方式使用, 则即使建立索引也会不奏效.
使用索引, 我们必须知道:
(1)创建索引
(2)命中索引
(3)正确使用索引
准备:
- #1. 准备表
- create table userinfo(
- id int,
- name varchar(20),
- gender char(6),
- email varchar(50)
- );
- #2. 创建存储过程, 实现批量插入记录
- delimiter $$ #声明存储过程的结束符号为 $$
- create procedure auto_insert1()
- BEGIN
- declare i int default 1;
- while(i<3000000)do
- insert into userinfo values(i,concat('alex',i),'male',concat('egon',i,'@oldboy'));
- set i=i+1;
- end while;
- END$$ #$$ 结束
- delimiter ; #重新声明分号为结束符号
- #3. 查看存储过程
- show create procedure auto_insert1\G
- #4. 调用存储过程
- call auto_insert1();
准备 300w 条数据
- - like '%xx'
- select * from userinfo where name like '%al';
- 使用函数
- select * from userinfo where reverse(name) = 'alex333';
- - or
- select * from userinfo where id = 1 or email = 'alex122@oldbody';
特别的: 当 or 条件中有未建立索引的列才失效, 以下会走索引
- select * from userinfo where id = 1 or name = 'alex1222';
- select * from userinfo where id = 1 or email = 'alex122@oldbody' and name = 'alex112'
- 类型不一致
如果列是字符串类型, 传入条件是必须用引号引起来, 不然...
- select * from userinfo where name = 999;
- - !=
- select count(*) from userinfo where name != 'alex'
特别的: 如果是主键, 则还是会走索引
- select count(*) from userinfo where id != 123
- ->
- select * from userinfo where name> 'alex'
特别的: 如果是主键或索引是整数类型, 则还是会走索引
- select * from userinfo where id> 123
- select * from userinfo where num> 123
- - order by
- select email from userinfo order by name desc;
当根据索引排序时候, 选择的映射如果不是索引, 则不走索引
特别的: 如果对主键排序, 则还是走索引:
select * from userinfo order by nid desc;
- 组合索引最左前缀
如果组合索引为:(name,email)
name and email -- 使用索引
name -- 使用索引
email -- 不使用索引
什么是最左前缀呢?
最左前缀匹配:
- create index ix_name_email on userinfo(name,email);
- select * from userinfo where name = 'alex';
- select * from userinfo where name = 'alex' and email='alex@oldBody';
- select * from userinfo where email='alex@oldBody';
如果使用组合索引如上, name 和 email 组合索引之后, 查询
(1)name 和 email --- 使用索引
(2)name --- 使用索引
(3)email --- 不适用索引
对于同时搜索 n 个条件时, 组合索引的性能好于多个单列索引
****** 组合索引的性能>索引合并的性能 *********
六, 索引的注意事项
(1)避免使用 select *
(2)count(1)或 count(列) 代替 count(*)
(3)创建表时尽量使用 char 代替 varchar
(4)表的字段顺序固定长度的字段优先
(5)组合索引代替多个单列索引(经常使用多个条件查询时)
(6)尽量使用短索引 (create index ix_title on tb(title(16)); 特殊的数据类型 text 类型)
(7)使用连接 (join) 来代替子查询
(8)连表时注意条件类型需一致
(9)索引散列 (重复少) 不适用于建索引, 例如: 性别不合适
七, 执行计划
来源: http://www.bubuko.com/infodetail-2650734.html