性能优化
最后更新于:2022-04-02 03:56:34
[TOC]
## 尽量去掉 in 与 or
```
select count(*) from stuff where id_no in('0','1')
//可以考虑将or子句分开:
select count(*) from stuff where id_no='0'
select count(*) from stuff where id_no='1'
```
## 把 in 转为 join
bad
```
SELECT
*
FROM
`im_msg_201907`
WHERE
msgstatus = 0
AND ( send_id = '6521' AND gid IN ( SELECT msgid FROM im_msg_rece_201907 WHERE RECEIVEID = '7415' ) )
OR ( send_id = '7415' AND gid IN ( SELECT msgid FROM im_msg_rece_201907 WHERE RECEIVEID = '6521' ) )
ORDER BY
send_date DESC
```
good
```
SELECT
im_msg_202103.*,
im_msg_rece_202103.RECEIVEID
FROM
`im_msg_202103`
LEFT JOIN im_msg_rece_202103 ON im_msg_rece_202103.MSGID = im_msg_202103.GID
WHERE
im_msg_202103.msgstatus = 0
AND ( im_msg_202103.send_id = '102' AND im_msg_rece_202103.RECEIVEID = '103' )
OR ( im_msg_202103.send_id = '103' AND im_msg_rece_202103.RECEIVEID = '102' )
ORDER BY
im_msg_202103.send_date DESC
```
## 用 not in 转为 left join 配合 is null
> thinkpphp 中 is null 表示为 `$where\['m\_order\_no'\] = array('exp','is null');`
## 优化**大分页**的查询(方式一)
bad
```
SELECT * FROM `year_score`
where `year` = 2017
ORDER BY id
limit (N - 1) * 20, 20;
```
good
```
# XXXX 代表已知的数据
SELECT * FROM `year_score`
where `year` = 2017 and id > XXXX
ORDER BY id limit 20;
```
## 优化**大分页**的查询(方式二)
当几百万的查询时候,优化效果明显
```
mysql > select id, name from test
where _timestamp >="2020-03-21 00: 00: 00" and
_timestamp <=2020-03-22 00: 00: 00" limit 0, 10;
(毫秒级)
mysql > select id, name from test
where _timestamp >="2020-03-21 00: 00: 00"
and _timestamp <=2020-03-22 00: 00: 00"
limit 1450000, 10;
(10.07s)
```
优化思路先把符合条件的主键找到,然后通过主键去定位符合条件的数据
1.通过索引覆盖避免了回表;2.通过主键直接定位数据的方法,省去了在数据集中查询初始位置的过程
1. 方案一:延迟关联法
```
SELECT
a.id,
a.NAME
FROM
test a,
( SELECT id FROM test
WHERE _timestamp >= "2020-03-21 00: 00: 00"
AND _timestamp <= "2020-03-22 00: 00: 00"
ORDER BY id LIMIT 1450000, 10
) b
WHERE
a.id = b = id :
```
2. 方案二: 键阈值法啊
```
SELECT
id,
NAME
FROM
test
WHERE
id >= (
SELECT id FROM test
WHERE _timestamp >= "2020-03-21 00: 00: 00"
AND _timestamp >= "2020-03-22 00: 00: 00"
LIMIT 1450000, 1
)
LIMIT 10
```
## hash(索引) 与 树(tree)
- 在单条查询记录时.hash 比 tree 快
- 排序查询(`group by` , `order by`, `< >`) tree比hash快
- InnoDB并不支持哈希索引
## 为什么InnoDB只有一个聚簇索引,而不将所有索引都使用聚簇索引
因为聚簇索引是将索引和数据都存放在叶子节点中,如果所有的索引都用聚簇索引,则每一个索引都将保存一份数据,会造成数据的冗余,在数据量很大的情况下,这种数据冗余是很消耗资源的
';