SQL 优化
UNION 和 OR,多个 OR 语句 使用 UNION 可以提高速度,表查询 使用 OR 可能导致索引失效。
LIKE 不能以 % 开头,可能导致索引失效。
使用查询语句 where 条件时,不能出现函数,可能导致索引失效。
组合索引遵循从 左到右 原则, 否则索引失效。SELECT * FROM table WHERE name = ‘zhangsan’ AND age = 18, 组合索引必须是 name,age 形式。
索引尽量不超过 10 个
表必须有主键 ,加快查询效率
分表,根据业务字段尾数中的个位或十位或百位(以此类推)做表名达到分表目的。
分库,根据业务字段尾数中的个位或十位或百位(以此类推)做表名达到分库目的。
表分区,类似硬盘分区,将某个时间段的时间放在分区里,加快查询速度,可配合 分表 + 表分区 结合使用。
MYSQL 神器:EXPLAIN 模拟优化器执行查询语句,分析查询语句或者表结构的性能瓶颈。EXPLAIN 文章
反向条件查询不能使用索引
1
2
3
4
5# no in / not exists 都不是好习惯
select from order where status != 0 and status != 1
# 优化为 in 查询
select from order where status in (2,3)前导模糊查询不能使用索引; 例如 LIKE %xxx
数据区分度不大的字段不宜使用索引;
1
2
3
4# 性别只有男 女,每次过滤掉的数据很少
select from user where sex =1
# 能过滤 80% 的数据时就可以使用索引。对于订单状态,如果状态很少,不宜使用索引,如果状态值很多,能都过滤大量数据,则应该建立索引。在属性上进行计算不能命中索引
1 | select from order where YEAR(data) <= '2017' |
非周知SQL优化实践
如果业务大部分是单条查询,使用 Hash 索引性能更好,例如用户中心
1
2
3
4select from user where uid =?
select from user where login_name=?
# 因为 B-Tree 索引时间复杂度是 O(log(n)), 而 Hash 索引时间复杂度是 O(1)允许 null 的列,查询有潜在坑,单列索引不存 null 值,复合索引不存全为 null 值,如果列允许为 null,可能会得到“不符合预期”的结果集
1
2
3select from user where name != 'shenjian'
# 如果 name 允许为 null 值,索引不存储 null 值,结果集中不会包含这些记录。所以,使用 not null 约束以及设置默认值符合索引最左前缀,并不是值 SQL 语句的 where 顺序要和复合索引一致
1
2
3
4
5
6
7
8
9
10
11# 用户中心建立了 (login_name, passwd) 的复合索引
select from user where login_name=? and passwd =?
select fron user where passwd=? and login_name=?
# 都能够命中索引
select from user where login_name=?
# 也能命中索引,满足复合索引最左前缀
select from user where passwd=?
# 不能命中索引,不满足复合索引最左前缀使用 ENUM 而不是字符串,ENUM 保持的是 TINYINT , 不要在枚举里插入 “中国”,“广东”,“技术部” 这样的字符串,字符串空间大,效率低。
小众有用
如果明确知道只有一条结果返回 limit 1 能够提高效率
1
2
3
4select from user where login_name=?
# 优化
select from user where login_name=? limit 1
# 你知道只有一条结果,但数据并不知道,明确告诉它,让其主动停止游标移动把计算放到业务层而不是数据库层,除了节省数据的 CPU,还有意想不到的查询缓存优化效果
1 | select from order where data <= CURDATE() |
强制类型转换会全表扫描
1
2
3
4
5select from user where phone=13712354789
# 这样不会命中 phone 索引
# 优化
select from user where phone='13712354789'不要使用 select * (文章里的 SQL 都不合格), 只需要返回需要的列,能够节省许多数据传输量,与数据库的内存使用量。
MYSQL 死锁
产生死锁的四个条件,只要发生死锁,这四个条件必然成立:
- 互斥条件:一个资源每次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对以获取的资源保持不放。
- 不剥夺条件:进程已获得的资源,在为使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
降低死锁概率:
- 按同一顺序访问对象
- 避免事务中的用户交互
- 保持事务的用户交互
- 保持事务简短并在一个批处理中
- 使用低隔离级别
- 使用绑定连接。
数据库索引的原理
数据库索引,是数据库管理系统中的一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引通常使用 BTree 以及变种 B+ Tree。B-Tree 索引通常非常占用内存,不能全部存储在内存中,但是如果存储在磁盘,索引查找的过程中就要产生磁盘 I/O 的消耗,索引的结构组织要尽量减少查找过程中磁盘 I/O 的存取次数。
https://www.cnblogs.com/soundcode/p/4454292.html
- 本文作者: MISAKIGA
- 本文链接: https://misakiga.github.io/2021/06/23/mysql/mysql_sql/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!
