Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
檀越@新空间
Coding Tree
提交
2f127475
C
Coding Tree
项目概览
檀越@新空间
/
Coding Tree
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Coding Tree
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
2f127475
编写于
5月 13, 2022
作者:
彭世瑜
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix
上级
136a4381
变更
7
显示空白变更内容
内联
并排
Showing
7 changed file
with
250 addition
and
1 deletion
+250
-1
blog/mysq-advance/img/innodb-store.png
blog/mysq-advance/img/innodb-store.png
+0
-0
blog/mysq-advance/img/page-merge-1.png
blog/mysq-advance/img/page-merge-1.png
+0
-0
blog/mysq-advance/img/page-merge-2.png
blog/mysq-advance/img/page-merge-2.png
+0
-0
blog/mysq-advance/img/page-split-1.png
blog/mysq-advance/img/page-split-1.png
+0
-0
blog/mysq-advance/img/page-split-2.png
blog/mysq-advance/img/page-split-2.png
+0
-0
blog/mysq-advance/index.md
blog/mysq-advance/index.md
+1
-1
blog/mysq-advance/sql-optimization.md
blog/mysq-advance/sql-optimization.md
+249
-0
未找到文件。
blog/mysq-advance/img/innodb-store.png
0 → 100644
浏览文件 @
2f127475
702.9 KB
blog/mysq-advance/img/page-merge-1.png
0 → 100644
浏览文件 @
2f127475
257.1 KB
blog/mysq-advance/img/page-merge-2.png
0 → 100644
浏览文件 @
2f127475
222.3 KB
blog/mysq-advance/img/page-split-1.png
0 → 100644
浏览文件 @
2f127475
246.5 KB
blog/mysq-advance/img/page-split-2.png
0 → 100644
浏览文件 @
2f127475
212.7 KB
blog/mysq-advance/index.md
浏览文件 @
2f127475
...
@@ -36,4 +36,4 @@ MySQL 运维篇
...
@@ -36,4 +36,4 @@ MySQL 运维篇
-
3.
[
https://www.yuque.com/heychu/akbndd/zhuxqd
](
https://www.yuque.com/heychu/akbndd/zhuxqd
)
-
3.
[
https://www.yuque.com/heychu/akbndd/zhuxqd
](
https://www.yuque.com/heychu/akbndd/zhuxqd
)
https://www.bilibili.com/video/BV1Kr4y1i7ru?p=90&spm_id_from=pageDriver
https://www.bilibili.com/video/BV1Kr4y1i7ru?p=92&spm_id_from=pageDriver
\ No newline at end of file
\ No newline at end of file
blog/mysq-advance/sql-optimization.md
浏览文件 @
2f127475
...
@@ -205,3 +205,252 @@ mysql> select count(*) from tb_user;
...
@@ -205,3 +205,252 @@ mysql> select count(*) from tb_user;
```
```
## 2、主键优化
### 2.1、数据组织方式
在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,
这种存储方式的表称为
`索引组织表`
(index organized table IOT)


### 2.2、页分裂
页可以为空,也可以填充一半,也可以填充100%。
每个页包含了2-N行数据(如果一行数据太大,会行溢出),根据主键排列
如果插入的数据主键不是顺序的,有可能发生页分裂


### 2.3、页合并
当删除一行记录的时候,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除。
并且它的空间变得允许被其他记录声明使用。
当页中删除的记录达到 MERGE_THRESHOLD (默认为页的50%),
InnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并优化空间使用。
MERGE_THRESHOLD : 合并也的阈值,可以自己设置,在创建表或者创建索引时指定


### 2.4、主键设计原则
1.
满足业务需求的情况下,尽量降低主键的长度(二级索引叶子节点存放主键,主键过长会占用大量磁盘空间)
2.
插入数据时,尽量选择顺序插入,选择使用
`auto_increment`
自增主键(不是顺序插入,会造成页分裂)
3.
尽量不要使用UUID做主键或者是其他自然主键,如身份证号(长度较长,耗费磁盘io)
4.
业务操作时,避免对主键的修改
## 3、order by 优化
-
using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在
`排序缓冲区sort buffer`
中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort排序
-
using index: 通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高
测试数据
```
sql
-- 查看表数据
mysql
>
select
*
from
tb_user
limit
3
;
+
----+-----------+-------------+---------------------+------+--------+----------------+
|
id
|
name
|
phone
|
profession
|
age
|
status
|
email
|
+
----+-----------+-------------+---------------------+------+--------+----------------+
|
1
|
费阳
|
13777763170
|
法务经理
|
27
|
1
|
wyao
@
gmail
.
com
|
|
2
|
祁海燕
|
13400806360
|
日式厨师
|
23
|
0
|
jwan
@
jin
.
cn
|
|
3
|
姬秀英
|
18281241586
|
食品
/
饮料研发
|
29
|
0
|
li97
@
wang
.
cn
|
+
----+-----------+-------------+---------------------+------+--------+----------------+
3
rows
in
set
(
0
.
01
sec
)
-- 查看索引
mysql
>
show
index
from
tb_user
;
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
Table
|
Non_unique
|
Key_name
|
Seq_in_index
|
Column_name
|
Collation
|
Cardinality
|
Sub_part
|
Packed
|
Null
|
Index_type
|
Comment
|
Index_comment
|
Visible
|
Expression
|
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
tb_user
|
0
|
PRIMARY
|
1
|
id
|
A
|
9804
|
NULL
|
NULL
|
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
0
|
idx_user_phone
|
1
|
phone
|
A
|
9804
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
0
|
idx_user_phone_name
|
1
|
phone
|
A
|
9804
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
0
|
idx_user_phone_name
|
2
|
name
|
A
|
9804
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_name
|
1
|
name
|
A
|
9130
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
1
|
profession
|
A
|
948
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
2
|
age
|
A
|
6232
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
3
|
status
|
A
|
7596
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_email_5
|
1
|
email
|
A
|
3955
|
5
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
9
rows
in
set
(
0
.
03
sec
)
-- 删除索引
drop
index
idx_user_phone
on
tb_user
;
drop
index
idx_user_phone_name
on
tb_user
;
drop
index
idx_user_name
on
tb_user
;
show
index
from
tb_user
;
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
Table
|
Non_unique
|
Key_name
|
Seq_in_index
|
Column_name
|
Collation
|
Cardinality
|
Sub_part
|
Packed
|
Null
|
Index_type
|
Comment
|
Index_comment
|
Visible
|
Expression
|
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
tb_user
|
0
|
PRIMARY
|
1
|
id
|
A
|
9804
|
NULL
|
NULL
|
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
1
|
profession
|
A
|
948
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
2
|
age
|
A
|
6232
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
3
|
status
|
A
|
7596
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_email_5
|
1
|
email
|
A
|
3955
|
5
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
5
rows
in
set
(
0
.
00
sec
)
```
索引测试
```
sql
-- 没有创建索引时,根据age, phone进行排序 Using filesort
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
age
,
phone
;
+
----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+----------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+----------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
ALL
|
NULL
|
NULL
|
NULL
|
NULL
|
9804
|
100
.
00
|
Using
filesort
|
+
----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+----------------+
1
row
in
set
,
1
warning
(
0
.
00
sec
)
-- 创建索引
create
index
idx_user_age_phone
on
tb_user
(
age
,
phone
);
-- 创建索引后,根据age进行升序排序
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
age
;
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
index
|
NULL
|
idx_user_age_phone
|
52
|
NULL
|
9804
|
100
.
00
|
Using
index
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-------------+
1
row
in
set
,
1
warning
(
0
.
00
sec
)
-- 创建索引后,根据age, phone进行升序排序
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
age
,
phone
;
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
index
|
NULL
|
idx_user_age_phone
|
52
|
NULL
|
9804
|
100
.
00
|
Using
index
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-------------+
1
row
in
set
,
1
warning
(
0
.
01
sec
)
-- 创建索引后,根据age, phone进行降序排序
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
age
desc
,
phone
desc
;
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+----------------------------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+----------------------------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
index
|
NULL
|
idx_user_age_phone
|
52
|
NULL
|
9804
|
100
.
00
|
Backward
index
scan
;
Using
index
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+----------------------------------+
1
row
in
set
,
1
warning
(
0
.
00
sec
)
-- 交换age,phone的先后位置 出现Using filesort
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
phone
,
age
;
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-----------------------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-----------------------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
index
|
NULL
|
idx_user_age_phone
|
52
|
NULL
|
9804
|
100
.
00
|
Using
index
;
Using
filesort
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-----------------------------+
1
row
in
set
,
1
warning
(
0
.
01
sec
)
-- age升序排列,phone降序排列,出现Using filesort
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
age
asc
,
phone
desc
;
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-----------------------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-----------------------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
index
|
NULL
|
idx_user_age_phone
|
52
|
NULL
|
9804
|
100
.
00
|
Using
index
;
Using
filesort
|
+
----+-------------+---------+------------+-------+---------------+--------------------+---------+------+------+----------+-----------------------------+
1
row
in
set
,
1
warning
(
0
.
00
sec
)
-- 创建age升序,phone降序的索引
create
index
idx_user_age_phone_ad
on
tb_user
(
age
asc
,
phone
desc
);
-- 查看索引 (Collation: A=asc, D=desc)
mysql
>
show
index
from
tb_user
;
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
Table
|
Non_unique
|
Key_name
|
Seq_in_index
|
Column_name
|
Collation
|
Cardinality
|
Sub_part
|
Packed
|
Null
|
Index_type
|
Comment
|
Index_comment
|
Visible
|
Expression
|
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
tb_user
|
0
|
PRIMARY
|
1
|
id
|
A
|
9804
|
NULL
|
NULL
|
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
1
|
profession
|
A
|
948
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
2
|
age
|
A
|
6232
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_profession_age_status
|
3
|
status
|
A
|
7596
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_email_5
|
1
|
email
|
A
|
3955
|
5
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_age_phone
|
1
|
age
|
A
|
11
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_age_phone
|
2
|
phone
|
A
|
9804
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_age_phone_ad
|
1
|
age
|
A
|
11
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
|
tb_user
|
1
|
idx_user_age_phone_ad
|
2
|
phone
|
D
|
9804
|
NULL
|
NULL
|
YES
|
BTREE
|
|
|
YES
|
NULL
|
+
---------+------------+--------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
9
rows
in
set
(
0
.
02
sec
)
-- 创建索引后,age升序排列,phone降序排列
mysql
>
explain
select
id
,
age
,
phone
from
tb_user
order
by
age
asc
,
phone
desc
;
+
----+-------------+---------+------------+-------+---------------+-----------------------+---------+------+------+----------+-------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+-------+---------------+-----------------------+---------+------+------+----------+-------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
index
|
NULL
|
idx_user_age_phone_ad
|
52
|
NULL
|
9804
|
100
.
00
|
Using
index
|
+
----+-------------+---------+------------+-------+---------------+-----------------------+---------+------+------+----------+-------------+
1
row
in
set
,
1
warning
(
0
.
00
sec
)
-- 如果没有用到覆盖索引,会出现:Using filesort
mysql
>
explain
select
*
from
tb_user
order
by
age
asc
,
phone
desc
;
+
----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+----------------+
|
id
|
select_type
|
table
|
partitions
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
filtered
|
Extra
|
+
----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+----------------+
|
1
|
SIMPLE
|
tb_user
|
NULL
|
ALL
|
NULL
|
NULL
|
NULL
|
NULL
|
9804
|
100
.
00
|
Using
filesort
|
+
----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+----------------+
1
row
in
set
,
1
warning
(
0
.
00
sec
)
```
### 3.1、优化原则
1.
根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
2.
尽量使用覆盖索引
3.
多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(asc/desc)
4.
如果不可避免的出现filesort, 大数据量排序时,可以适当增大排序缓冲区的大小 sort_buffer_size(默认值256k)
```
sql
mysql
>
show
variables
like
'sort_buffer_size'
;
+
------------------+--------+
|
Variable_name
|
Value
|
+
------------------+--------+
|
sort_buffer_size
|
262144
|
+
------------------+--------+
1
row
in
set
(
0
.
03
sec
)
```
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录