MySQL/索引
1.索引:
索引是表的目录,在查找内容之前可以先在目录中查找索引位置,此次快速定位查询数据。对于索引,会保存在额外的文件中。
1.1 MySQL中常见索引有:
主键索引:加速查找+不能为空+不能重复
普通索引:加速查找
唯一索引:加速查找+不能重复
组合索引(多列):- 联合主键索引 - 联合唯一索引 - 联合普通索引
1.2 作用:约束、加速查找
1.3 创建普通索引:
create index 索引名称 on userinfo3(email);
删除索引:
drop index_name on userinfo3;
查看索引:
show index from userinfo3;
注意:对于创建索引是如果是blob和text类型,必须指定length。
create index ix_extra on userinfo3(extra(32));
1.4索引种类(某种格式存储):
hash索引:单值查找快 查找范围
btree索引:二叉树
结果:快
2.建立索引:
a:额外的文件保存特殊的数据结构
b:查询快,插入更新删除慢
c:命中索引:如你创建了一个email的索引,要查找的时候需要根据命名的索引进行查找,这样查找速度快
select *from userinfo3 where email = 'asdf'; 查询速度快 select *from userinfo3 where email like 'asdf'; 查询速度慢
主键索引:
普通索引:
create index 索引名称 on 表名(列名)
drop index 索引名称 on 表名 删除索引
唯一索引:
create unique index 索引名称 on 表名(列名)
drop unique index 索引名称 on表名
组合索引(最左前缀匹配):
create unique index 索引名称 on 表名(列名,列名)
drop unique index 索引名称 on 表名
create unique index ix_name_email on userinfo3(name,email)
最左前缀匹配: 顾名思义,就是最左优先 select *from userinfo3 where name ='alex'; select *from userinfo3 where name='alex' and email='asdf'; 查询速度快 select *from userinfo3 where email='alex@qq.com'; 不是前缀匹配 组合索引(多列):多列值组成一个索引,专门用于组合搜索效率大于索引合并 (name,email) select *from userinfo3 where name ='alex'; select *from userinfo3 where name='alex' and email='asdf'; 索引合并(单列):把多个单列索引合并使用 name email select *from userinfo3 where name=“alex”and email='asdf'; select *from userinfo3 where name=‘alex’; select *from userinfo3 where email=‘alex’; 索引覆盖:在索引文件中直接获取数据 全文索引:对文本的内容进行分词,进行搜索
3. 频繁查找的列创建索引:
- 创建索引
- 命中索引 *****联合使用
即时建立索引,索引也不会生效:
- like '%xx' select * from tb1 where name like '%cn'; - 使用函数 select * from tb1 where reverse(name) = 'wupeiqi'; - or select * from tb1 where nid = 1 or email = 'seven@live.com'; 特别的:当or条件中有未建立索引的列才失效,以下会走索引 select * from tb1 where nid = 1 or name = 'seven'; select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex' - 类型不一致 如果列是字符串类型,传入条件是必须用引号引起来,不然... select * from tb1 where name = 999; - != select * from tb1 where name != 'alex' 特别的:如果是主键,则还是会走索引 select * from tb1 where nid != 123 - > select * from tb1 where name > 'alex' 特别的:如果是主键或索引是整数类型,则还是会走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 - order by select email from tb1 order by name desc; 当根据索引排序时候,选择的映射如果不是索引,则不走索引 特别的:如果对主键排序,则还是走索引: select * from tb1 order by nid desc;
其他注意事项:
- 避免使用select * - count(1)或count(列) 代替 count(*) - 创建表时尽量使 char 代替 varchar - 表的字段顺序固定长度的字段优先 - 组合索引代替多个单列索引(经常使用多个条件查询时) - 尽量使用短索引 - 使用连接(JOIN)来代替子查询(Sub-Queries) - 连表时注意条件类型需一致 - 索引散列值(重复少)不适合建索引,例:性别不适合
4.执行计划
explain+查询sql -用于显示sql执行信息参数,根据参考信息可以进行sql优化
mysql> explain select *from useru;
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra +----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------+ | 1 | SIMPLE | useru | NULL | ALL | NULL | NULL | NULL | NULL | 1835575 | 100.00 | NULL +----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------+ 1 row in set, 1 warning (0.01 sec)
all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
慢: select * from userinfo3 where name='alex' explain select * from userinfo3 where name='alex' type: ALL(全表扫描) select * from userinfo3 limit 1; 快: select * from userinfo3 where email='alex' type: ref const(走索引)
mysql> explain select *from useru where uname="alex122";
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+ | 1 | SIMPLE | useru | NULL | ref | inss | inss | 766 | const | 1 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.06 sec)
mysql> explain select *from useru;
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------+ | 1 | SIMPLE | useru | NULL | ALL | NULL | NULL | NULL | NULL | 1835575 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+------+---------+------+---
5.慢日志
a:配置mysql自动记录慢日志 slow_query_log = OFF 是否开启慢日志记录 long_query_time = 2 时间限制,超过此时间,则记录 slow_query_log_file = /usr/slow.log 日志文件 log_queries_not_using_indexes = OFF 为使用索引的搜索是否记录
注:查看当前配置信息:
show variables like '%query%'
修改当前配置:
set global 变量名=值
b:配置文件 - 配置文件 mysqld--defaults-file='E:\wupeiqi\mysql-5.7.16-winx64\mysql-5.7.16-winx64\my-default.ini' 路径 my.conf内容: slow_query_log = ON slow_query_log_file = D:/....路径 注意:修改配置文件之后,需要重启服务 修改配置文件之前,需要备份
6.分页******
- 索引表中扫:
select * from userinfo3 where id in(select id from userinfo3 limit 200000,10);
方案:记录当前页最大或最小ID
1.页面只有上一页,下一页
# max_id
# min_id
下一页:
select * from userinfo3 where id > max_id limit 10; mysql> select *from useru where id >20000 limit 10;
上一页:
select * from userinfo3 where id < min_id order by id desc limit 10; mysql> select *from useru where id <20000 order by desc id limit 10;
2.上一页 192 193 [196] 197 198 199 下一页
上一页:
select * from tb1 where nid < (select nid from (select nid from tb1 where nid < 当前页最小值 order by nid desc limit 每页数据 *【页码-当前页】) A order by A.nid asc limit 1) order by nid desc limit 10; select * from tb1 where nid < (select nid from (select nid from tb1 where nid < 970 order by nid desc limit 40) A order by A.nid asc limit 1) order by nid desc limit 10;
下一页:
select * from tb1 where nid < (select nid from (select nid from tb1 where nid > 当前页最大值 order by nid asc limit 每页数据 *【当前页-页码】) A order by A.nid asc limit 1) order by nid desc limit 10; select * from tb1 where nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc limit 20) A order by A.nid desc limit 1) order by nid desc limit 10;