https://www.jianshu.com/p/fdd3c5e815e9
本课程,适合具备一定Linux运维或者开发基础的朋友,课程定级中、高级DBA。
只要掌握80%,轻松助力薪资15k-25K。
课程内容均来自与MySQL官网+MySQL源码。
配套精品视频(2021 5月全新录制,版权所有:郭加磊 oldguo。),获取方法私聊。
相当于一本书中的目录,可以加速查询(select ,update,delete ).
Btree (平衡多叉树): b-tree b+tree(b*tree),优点:范围查找
HASH : 优点,比较适合随机的等值.
Rtree
聚簇索引 : 主键索引
辅助索引 :
单列
联合
唯一
前缀
mysqlslap --defaults-file=/etc/my.cnf \
--concurrency=100 --iterations=1 --create-schema='test' \
--query="select * from test.t100w where k2='VWlm'" engine=innodb \
--number-of-queries=2000 -uroot -p123 -verbose
a. desc city;
PRI : 主键索引
MUL : 普通索引
UNI : 唯一索引
b. show index from city;
Table 表名
Key_name 索引名
Column_name 列名
Cardinality 基数(选择度),位置值的多少
Cardinality 建立索引之前,基数如何计算的?
select count(distinct countrycode) from city;
alter table city add index i_name(name);
alter table city add index i_d_p(distinct,population);
alter table city add index i_x(name(10));
alter table t1 add unique index i_a(a);
alter table city drop index i_name;
mysql> alter table city alter index idx_name invisible;
SELECT INDEX_NAME, IS_VISIBLE
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'world' AND table_name='city';
不管查找哪个数,需要查找次数理论上是相同的.对于一个三层b树来讲,理论上查找每个值都是三次IO.
讲究快速锁定范围.
B+tree,加入了双向指针(头尾相接),进一步增强范围查找.减少对于ROOT和NON-LEAF的访问次数.
叶子: 先将数据排序,生成叶子节点.
枝 : 保存叶子节点的范围(>=1 <5)+指针(→)
根 : 保存枝节点范围+指针
叶子节点和枝节点都有双向指针.
区(簇)extent : 连续的64pages ,默认是1M存储空间.
page页 : 16KB大小,MySQL中最小的IO单元.
数据应该按照索引结构有序(顺序)组织和存储数据.
MySQL使用聚簇索引组织存储数据.
a. 如果表中有主键,主键就被作为聚簇索引.
b. 没有主键,第一个不为空的唯一键.
c. 什么都没有,自动生成一个6字节的隐藏列,作为聚簇索引.https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html
叶子节点: 聚簇索引组织表,存数据时,已经是按照ID列有序存储数据到各个连续的数据页中.原表数据存储结构就是叶子节点.
枝节点 : 叶子节点中ID范围+指针
根节点 : 枝节点的ID范围+指针
只能优化基于ID作为条件.索引单纯使用ID列查询,很局限.
需要人为按照需求创建辅助索引.
alter table t1 add index idx(name);
叶子节点 : 将辅助索引列值(name)+ID提取出来,按照辅助索引列值从小到大排序,存储到各个page中,生成叶子节点.
枝节点 : 存储了叶子节点中,name列范围+指针.
根节点 : 枝节点的name的范围+指针.
如果查询条件使用了name列,都会先扫描辅助索引,获得ID,再回到聚簇索引(回表),按照ID进行聚簇索引扫描,最终获取到数据行.
https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html
alter table t1 add index idx_n_g(a,b)
叶子节点 : 提取a+b+id列值,按照a,b联合排序(从小到大),生成叶子节点.
枝节点 : 叶子节点最左列范围+指针
根节点 : 枝节点的范围+指针.
查询条件中必须包含最左列条件(a),先通过 a条件 扫描联合索引的根节点和枝节点,从而得到叶子节点范围.再拿b作为条件过滤一次.
最终目的,得到更精确的ID .理论上减少回表的次数.
建立联合索引时,选择基数大(重复值少)作为最左列.
查询条件中必须要包含最左列条件.
一般建议3-4层为佳,3层b树,2000w+.
a. 数据行多
分区表.
定期归档: 一般按照时间字段,定期归档到历史库中. pt-archiver.
分库分表:分布式
b. 索引列长度过长
前缀索引.
c. 数据类型
足够
简短
合适
辅助索引扫描之后,得到ID,再回到聚簇索引查找的过程.
IO : 次数和量会增加.
IOPS : 1000次/s
吞吐量 : 300M/s
a. 建索引使用联合索引(覆盖),尽可能多将查询条件的数据包含联合索引中.
b. 精细查询条件(业务方面,> and < ,limit)
c. 查询条件要符合联合索引规则,覆盖的列越多越好.
AHI : 索引的索引. 为内存中的热点索引页,做了一个HASH索引表,能够快速找到需要的索引页地址.
https://dev.mysql.com/doc/refman/8.0/en/innodb-adaptive-hash.html
https://dev.mysql.com/doc/refman/8.0/en/innodb-architecture.html
change buffer :
对于辅助索引的变化,不会立即更新到索引中.暂存至change buffer .
https://dev.mysql.com/doc/refman/8.0/en/innodb-change-buffer.html
优化器(算法)最终得出的,代价最低的,SQL语句的执行方案.
场景一: 分析比较慢的语句.
场景二: 上线新业务,可能会包含很多select update delete...,提前发现问题.
select update delete
mysql> desc select * from world.city where countrycode='CHN';
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | city | NULL | ref | CountryCode | CountryCode | 3 | const | 363 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+------