1.索引 作用: - 约束 - 加速查找 索引分类(约束): - 普通索引:加速查找 - 主键索引:加速查找 + 不能为空 + 不能重复 - 唯一索引:加速查找 + 不能重复 - 联合索引(多列) : - 联合主键索引 - 联合唯一索引 - 联合普通索引 索引分类(加速查找): hash索引: 索引表存储(哈希值的顺序和数据表中的数据顺序不相同): 1.所有索引列数据转换成的哈希值 2.索引列数据的内存地址 hash索引优点: 查找单个值快 查找范围值慢 btree索引:二叉树(innodb) 二叉树存储: 先将索引列数据转化成数字,每个二叉树节点存储一个数字及索引列数据的地址, 二叉树节点的数字与子节点的数字有顺序关系(左子节点数字小于父节点,有子节点数字大于父节点) hash索引优点: 查找单个值慢 查找范围值快 建立索引:
- a.额外的文件保存特殊的数据结构
- b.查询加快,插入更新删除相对也会变慢
- c.命中索引(此处email列建立了索引)
select * from userinfo where email = 'asdf';
# 由于未命中索引,查询速度慢
select * from userinfo where email like 'asdf';
普通索引:
- create index 索引名称 on 表名(列名)
- drop index 索引名称 on 表名
唯一索引:
- create unique index 索引名称 on 表名(列名)
- drop unique index 索引名称 on 表名
组合(唯一)索引:
- create unique index 索引名称 on 表名(列名,列名)
- drop index 索引名称 on 表名
- create unique index ix on userinfo3(name,email);
- 最左前缀匹配(组合索引(name,email))
select * from userinfo3 where name='alex';
select * from userinfo3 where name='alex' and email='asdfg';
# 无法使用索引,组合索引会优先匹配组合中左边的列
select * from userinfo3 where email='asdfg';
组合索引效率>索引合并
名词:
覆盖索引:
- 在索引文件中直接获取数据(此处sid是索引)
select sid from userinfo where sid = 5;
索引合并:
- 把多个单列索引合并使用,对多列单独建立索引一起使用
select * from userinfo3 where name='alex' and email='asdfg';
部分索引(text类的使用短索引):
create index ix__ on tb1(title(15)) 表示对title列前15个字符进行索引
2.不能命中索引情况:
- like '%xx'
# name是索引,但是使用like和通配符进行查找,不能命中索引
select * from tb1 where name like '%cn';
- 使用函数
# email是索引,但是使用reverse函数后不会命中索引
select * from tb1 where reverse(email) = 'alex155@163.com';
- or(仅当or中没有建立索引的列才会不使用索引)
# nid是索引 name不是索引 email是索引
select * from tb1 where nid = 1 or name = 'alex';
# 以下会走索引
select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
- 类型不一致(主键除外)
# nid int类型,name是varcha类型
select * from tb1 where nid = 1 or name = 888;
- !=(主键除外)
# name是索引,使用!=不能命中索引
select * from tb1 where name != 'alex';
- >(主键和整数类型除外)
# name是索引,使用>不能命中索引
select * from tb1 where name >'alex';
- order by(主键除外)
# 当根据索引排序时候,选择的映射如果不是索引,则不走索引
select name from tb1 order by email desc;
3.其他注意事项(不同的数据库情况不同) - 避免使用select * - count(1)或count(列) 代替 count(*) - 创建表时尽量时 char 代替 varchar - 表的字段顺序固定长度的字段优先 - 组合索引代替多个单列索引(经常使用多个条件查询时) - 尽量使用短索引 - 使用连接(JOIN)来代替子查询(Sub-Queries) - 连表时注意条件类型需一致 - 索引散列值(重复少)不适合建索引,例:性别不适合4.时间 执行计划(explain):让mysql预估执行操作 查询时的访问方式: 性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
慢:
explain select * from userinfo3 where name = 'alex'
type = all(全表扫描)
快:
explain select * from userinfo3 where email = 'alex'
type = ref(索引查找)
5.DBA工作 慢日志 - 执行时间 >10 - 未命中索引 - 日志文件路径 配置 - 在内存中设置
# 查询变量
show variables like '%query%'
show variables like '%queries%'
# 打开慢查询日志
set global slow_query_log = ON
# 记录没有使用索引的SQL
set global log_queries_not_using_indexes = ON
# 设置慢日志文件存储地址 set slow_query_log_file = D:/....
- 在配置文件中设置(启动客户达端时可以指定配置文件的地址) 注意:修改配置文件之后,需要重启服务
mysqld --defaults-file = 'D:\my.conf'
my.conf中添加内容: # 打开慢查询日志
slow_query_log = ON # 记录没有使用索引的SQL set global log_queries_not_using_indexes = ON
# 设置慢日志文件存储地址 slow_query_log_file = D:/....
6.分页(基于数据库实现类似网页中的分页功能) 问题:同时对大量的数据进行分页会浪费很多时间 方案一:只给用户看到若干页面 缺点:这样不能在根本上解决问题 方案二:索引表 缺点:在索引中扫描比在数据表中速度快,但是实际上不能加快很多,本质上还得扫描200000条数据
select * from userinfo3 where id in(select id from userinfo3 limit 200000,10);
方案三:记录当前页 (id不一定连续,所以无法直接使用id范围进行查找)
1.页面只有上一页,下一页
# max_id 当前页面的最大id
# min_id 当前页面的最小id
下一页
select * from userinfo3 where id > max_id limit 10;
上一页
select * from userinfo3 where id < max_id order by desc limit 10;
2.上一页 192 193 196 197 198 199 x下一页
# 当前处于193页,需要跳到196页
select * from userinfo3 where id in (
select id from (select * from userinfo3 where id > max_id limit 30) as N order by N.id desc limit 10;
)