MySQL索引常用操作及SQL优化

MySQL索引常用操作及SQL优化

基本操作

基本操作

1. 创建索引
普通索引:
# 创建普通索引
create index idx_student_info_name on student_info(name);


唯一索引:
# 创建唯一索引
create unique index idx_student_info_code on student_info(code);


联合索引:
# 创建联合索引
create index idx_student_info_gender_age on student_info(gender, age);

# 创建索引时指定排序方式
# gender 字段升序排列, age 字段降序排列.
create index idx_student_info_gender_age on student_info(gender asc, age desc);


前缀索引:
# 创建前缀索引, 将 code 字段前两个字符截取出来作为索引, 将大大缩减索引存储容量.
create index idx_student_info_code on student_info(code(2));
# 使用前缀索引时需配合此 SQL 来评估索取字符长短(列数据重复率). 
# 此值越趋近于1越好, 而索引字符长度则是越短越好, 需在此值和索引字符长度间做取舍.
select count(distinct substring(code, 1, 2)) / count(*) from student_info

2. 查看索引
show index from student_info;

关键字解释:
Key_name:		索引名称
Seq_in_index:	索引排序
Column_name:	索引列
Collation:		索引排序方式, 取值: A升序, D降序
Cardinality:	索引中不重复记录的预估值
Sub_part:		前缀索引中的前缀长度, 如果整列被编入索引, 则为 NULL
Packed:			指示关键字如何被压缩, 如果没有被压缩, 则为 NULL
Null:			如果列可以含有NULL,则取值为YES.
Index_type:		索引类型

3. 删除索引
drop index idx_student_info_code on student_info;

4. 索引使用及失效
4.1. 最左前缀法则

最左前缀法则 是指使用联合索引时, 查询是从最左侧列开始, 并且不跳过索引中的列, 如果跳过某一列, 后面列的索引将失效.

# 例如:
# 创建联合索引为:
create index idx_student_info_name_age_score on student_info(name, age, score);

# 索引有效
select * from student_info where name = 'AA';
select * from student_info where name = 'AA' and age = 15 and score = 80;
# 查询顺序MYSQL会自动优化, 所以此处也会使用索引.
select * from student_info where age = 15 and score = 80 and name = 'AA';

# 索引失效
select * from student_info where age = 15;
select * from student_info where score = 80;
select * from student_info where age = 15 and score = 80;

# 部分索引失效, name 列将会使用索引, 因为跳过了 age 列, 索引 score 列将不会使用索引.
select * from student_info where name = 'AA' and score = 80;

4.2. 不在索引列使用运算操作
例如:
# 索引失效
explain SELECT * FROM `student_info` where substring(code, 3, 1) = '1';
4.3. 字符串类型不加引号

字符串类型字段(varchar, char 等) 查询时作为条件需要加引号.

例如:
# 索引有效
explain SELECT * FROM `student_info` where code = '100';

# 索引失效
explain SELECT * FROM `student_info` where code = 100;
4.4. 模糊查询( Like )

使用模糊查询时, 匹配符 % 在左侧时, 索引失效, 匹配符 % 在右侧时, 索引有效.

例如:
# 索引有效
select * from student_info where name like 'A%';

# 索引失效
select * from student_info where name like '%A';
select * from student_info where name like '%A%';
4.5. OR 查询规则

使用 OR 关键字作为查询条件是, 必须左右两侧同时有索引, 索引才会有效, 若只有一侧有索引, 则索引失效.

例如:
# 创建3列, name列, code列, age列, name和code创建索引. age不创建索引.
create index idx_student_info_name on student_info(name);
create index idx_student_info_code on student_info(code);

# 索引有效
select * from student_info where name = 'AA' or code = '100';

# 索引失效
select * from student_info where name = 'AA' or age = 18;
select * from student_info where age = 18 or code = '100';
4.6. 数据分布评估

mysql 优化器会对查询SQL及数据进行评估, 如果评估结果为使用全表扫描效率比使用索引高, 则也会索引失效.

例如:
# 索引有效
# 查询年龄小于15的人. 查询结果数据只有总数据的40%, 所以会使用索引.
select * from student_info where age <= 15

# 索引失效
# 查询年龄所有小于100的人, 该查询出来的数据已经占了总数据的100%, 所以不使用索引. 全表扫描比较快.
select * from student_info where age <= 100
4.7. IS NULL 和 IS NOT NULL

IS NULL 和 IS NOT NULL 是否使用索引也遵循数据分布评估.


5. 索引建议

当条件列存在多个索引时, 可以建议mysql 使用索引 sql优化的重要手段
use index 建议使用索引.
ignore index 不使用索引.
force index 强制使用索引.

例如:
# 建议使用 idx_student_info_name, 但mysql不一定会使用.
select * from student_info use index(idx_student_info_name) where name = 'AA';

#  不使用 idx_student_info_name 索引.
select * from student_info ignore index(idx_student_info_name) where name = 'AA';

#  强制使用 idx_student_info_name 索引.
select * from student_info force index(idx_student_info_name) where name = 'AA';

6. Limit优化

使用 limit 关键字分页时, 前面的便宜值越大, 查询效率越慢.

例如:
# 此查询效率高
SELECT * FROM student_info LIMIT 0, 10;
# 此查询效率低下
SELECT * FROM student_info LIMIT 1000000, 10;

建议使用 覆盖索引 + 子查询的方法优化

例如:
# 使SQL使用覆盖索引.
select gid from student_info order by gid limit 1000000, 10;

# 使用 覆盖索引 + 子查询 优化 limit 分页.
select a.* from student_info a, (select gid from student_info order by gid limit 1000000, 10) b where a.gid = b.gid

7. Update优化

InnoDB 的行锁是针对索引加的锁, 不是针对记录加的, 并且该索引不能失效, 否则会从行锁升级为表锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值