-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
wanglekai
committed
Jan 9, 2021
1 parent
7099b4a
commit 90725b7
Showing
1 changed file
with
50 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# database optimization notes | ||
Just personal notes for my own convenience. | ||
|
||
## 索引优化规则 | ||
|
||
- like 语句的前导模糊查询不能使用索引。 | ||
- union、in、or 都能够命中索引,建议使用 in。 | ||
- union 能够命中索引,并且 MySQL 耗费的 CPU 最少。 | ||
- `in` 能够命中索引,查询优化耗费的 CPU 比 `union all` 多,但可以忽略不计,一般情况下建议使用 in。、 | ||
- `or` 新版的 MySQL 能够命中索引,查询优化耗费的 CPU 比 `in` 多,不建议频繁用 `or`。 | ||
- 有些地方说在 `where` 条件中使用 `or`,索引会失效,造成全表扫描,这是个误区: | ||
- 要求 `where` 子句使用的所有字段,都必须建立索引。 | ||
- 如果数据量太少,mysql 制定执行计划时发现全表扫描比索引查找更快,所以会不使用索引。 | ||
- 确保 mysql 版本 5.0 以上,且查询优化器开启了 `index_merge_union = on`, 也就是变量 `optimizer_switch` 里存在 `index_merge_union` 且为 `on`。 | ||
- 负向条件查询不能使用索引。 | ||
- 负向条件有:`!=、<>、not in、not exists、not like` 等。 | ||
- 联合索引最左前缀原则。 | ||
- 建立联合索引的时候,区分度最高的字段在最左边。 | ||
- 存在非等号和等号混合判断条件时,在建立索引时,把等号条件的列前置。如 `where a>? and b=?`,那么即使 `a` 的区分度更高,也必须把 `b` 放在索引的最前列。 | ||
- 最左前缀查询时,并不是指 SQL 语句的 where 顺序要和联合索引一致。 | ||
- 不能使用索引中范围条件右边的列(范围列可以用到索引),范围列之后列的索引全失效。 | ||
- 范围条件有:`<、<=、>、>=、between` 等。 | ||
- 索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。 | ||
- 假如有联合索引 `(empno、title、fromdate)`,那么下面的 SQL 中 `emp_no` 可以用到索引,而 `title` 和 `from_date` 则使用不到索引。 | ||
- 不要在索引列上面做任何操作(计算、函数),否则会导致索引失效而转向全表扫描。 | ||
- 强制类型转换会全表扫描。 | ||
- 字符串类型不加单引号会导致索引失效,因为mysql会自己做类型转换,相当于在索引列上进行了操作。 | ||
- 更新十分频繁、数据区分度不高的列不宜建立索引。 | ||
- 更新会变更 B+ 树,更新频繁的字段建立索引会大大降低数据库性能。 | ||
- “性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似。 | ||
- 一般区分度在80%以上的时候就可以建立索引,区分度可以使用 `count(distinct(列名))/count(*)` 来计算。 | ||
- 利用覆盖索引来进行查询操作,避免回表,减少 `select *` 的使用。 | ||
- 索引不会包含有NULL值的列。 | ||
- 只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时,尽量使用not null 约束以及默认值。 | ||
- is null, is not null 无法使用索引。 | ||
- 如果有 order by、group by 的场景,请注意利用索引的有序性。 | ||
- 使用短索引(前缀索引)。 | ||
- 利用延迟关联或者子查询优化超多分页场景。 | ||
- 如果明确知道只有一条结果返回,limit 1 能够提高效率。 | ||
- 超过三个表最好不要 join。 | ||
- 单表索引建议控制在5个以内。 | ||
- SQL 性能优化 explain 中的 type:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。 | ||
- 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。 | ||
- 不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的。另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。 | ||
- 创建索引时避免以下错误观念: | ||
- 索引越多越好,认为需要一个查询就建一个索引。 | ||
- 宁缺勿滥,认为索引会消耗空间、严重拖慢更新和新增速度。 | ||
- 抵制惟一索引,认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。 | ||
- 过早优化,在不了解系统的情况下就开始优化。 | ||
|