• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
CaoJianbang
邦哥
博客园    首页    新随笔    联系   管理    订阅  订阅

索引优化

1. 尽量全值匹配

当建立索引后,能再where条件中使用索引列,就尽量使用。
例如 alter table staffs add index idx_staffs_nameAgePos(name,age,pos);
尽量加上三个列在where里,EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'dev'

2. 最佳左前缀法则

如果是复合索引,就要遵守最左前缀法则,意思是:查询从最左前列开始,并且不跳过索引中的列。
同样索引列是name,age,pos。
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July'; (会用索引NAME )
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND AGE = 25;(会用索引NAME 和AGE)
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND POS= 'dev'(只会用到NAME,因为跳过了AGE)
EXPLAIN SELECT * FROM staffs WHERE AGE = 25 AND POS='dev';(不会用索引,因为最左前列NAME没有使用)

3. 不在索引列上做任何操作

不在索引列上(计算,函数,自动或者手动的进行类型转换),会导致索引失效。
EXPLAIN SELECT * FROM staffs WHERE left(NAME,4) = 'July';(不会用到索引)

4. 范围条件放最后(是指索引定义顺序的最后)

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' and age =22 and pos='manager'
中间有范围查询会导致后面的索引列全部失效(按照name,age,pos,索引创建的顺序,age后面的POS会失效)
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' and age >22 and pos='manager' (索引只会用到NAME 和AGE列)
对于in条件查询,如果索引没有生效,使用in不会有影响;如果索引有效,使用in则会进行全表扫描
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' and age = 22 and pos in ('a','b' ) (name,age,pos索引都存在,没有跳过的,pos使用in则会导致全表扫描)
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' and pos in ('a','b' ) (索引age跳过了,所以pos不会生效,加in不会对索引有影响)

5. 尽量使用覆盖索引

覆盖索引(只访问索引的查询(索引列和查询列一致)),而尽量避免 select *

6. 不等于要慎用

在使用不等于(!= 或者<>),会导致索引失效
EXPLAIN SELECT * FROM staffs WHERE NAME <> 'July';
如果定要需要使用不等于,请用覆盖索引
EXPLAIN SELECT name,age,pos FROM staffs WHERE NAME != 'July';

7. NULL和Not NULL要慎用

|-- 在字段为NOT NULL的情况下,如果使用 is null 或者 is not null,会导致索引失效。解决方案(覆盖索引)
EXPLAIN select * from staffs where name is not null (索引失效)
EXPLAIN select name,age,pos from staffs where name is not null (可以使用索引)
|-- 在字段为可以为NULL的情况下,使用IS NULL,索引正常;使用 IS NOT NULL,则索引失效。(解决方案同上,覆盖索引)

8. LIKE查询要当心

like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作。
EXPLAIN select * from staffs where name like '%july%' (索引失效,一定要用的话,用覆盖索引)
EXPLAIN select * from staffs where name like 'july%' (可以使用索引,类似遵循最左前缀原则)

9. 字符类型加引号

EXPLAIN select * from staffs where name = 917 (索引失效)
EXPLAIN select * from staffs where name = ‘917’ (可以使用索引)

10. OR改UNION效率高

EXPLAIN select * from staffs where name='July' or name = 'z3' (索引失效,解决方案UNION或者覆盖索引)
|-- 解决方式:UNION
EXPLAIN
select * from staffs where name='July'
UNION
select * from staffs where name = 'z3'
|-- 解决方式:覆盖索引
EXPLAIN
select name,age from staffs where name='July' or name = 'z3'

除了索引优化之外,还有一些查询优化的技巧:

1. 延迟关联

select c1 from table where c2='M' order by c3 limit 100000, 10; 类似这种分页查询
可以通过延迟关联(deferred join)技术,通过覆盖索引(c2+c3)来得到所需要的主键,然后再根据这些主键关联原表获得需要的行。

select c1
from table, (select id from table where c2='M' order by c3 limit 100000, 10) as table2
where table.id = table2.id
2. LIMIT 1

当查询结果只可能为1条数据的时候,加上LIMIT 1可以增加性能,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。

 

 

 

 

in是否会走索引

in通常会走索引,但是数据量较大时,不走索引

 

深度分页优化

使用子查询:

select * from user where id in ( select id from user where age = 12 limit 1000000,10 )

使用管理查询

select * from user inner join ( select id from user where age = 12 limit 1000000,10) as t1 on user.id = t1.id

如果是瀑布流,可通过获取最后的id才查

select * from user where age =12 and id >? limit 100000000,10

 

多表联合查询优化

 

posted @ 2022-11-03 16:29  CaoJianbang  阅读(101)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3