开发者学堂课程【数据库常见问题排查:常见问题排查方法】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/68/detail/1169
常见问题排查方法
因为 C2上没有索引。所以没有 B+Tree,同时 C2是一个没有唯一性的约束,他可能会有很多个值,那在 C2查找的时候不是很好有思路。因为 C2没有办法去很快去定位到他,只能采用最原始的方法。从第一行一直要扫到最后一行,这个表的数据量是一千万行,如果要找到所有满足 C2的条件的,需要把一千万行所在的 page 全部都去寻找一遍。那对应的 page 数也就是对应的IO数,所以可以看到,一个 page 下面可以存放50行主键。所以这个是一千万行的一张表,然后除以50大约是20万的IO,从这个对比来看,可以看到主键索引,非主键索引,以及全表扫描下的 IO 消耗,补充一个点,就是在全表扫描的时候,第一次是随机 IO,后面都是一个顺序 IO,但通过这个数字也是非常能够体现出使用索引的一个差距。
扩展内容比如是主键的长度,在这个案例中,主键的长度是四个字节,如果主键的长度扩展到16个字节,那在第二层第三层第四层它能支撑的数据量都会有一个变化,如果主键增长到16个字节。然后到三层的时候,它能支撑的行数是1250万行左右。所以也就意味着它能支撑的行数降到了1/4,如果表格数据量超过1250行,每次主键查询上 IO 都会增加一次。如果在回表的数量非常多的这种情况下,它其实是一个放大。所以这里还是要注意。MySQL 能支撑多大的数据量,通过刚才的分析,一张表,它能支撑的数据量和表结构设计有关,和 SQL 也相关。具体能支撑的数量要结合应用具体分析。
4.查询代价
-主键查询优先于二级索引查询(非主键查询)
-二级索引扫描优先于全表扫描
-单表查询优先于连接查询,表连接数量越少越好
在 nice group index join 的情况下的 IO 消耗,IO 消耗上的一个值你可以认为是等于驱动表的全表扫描的 IO 消耗乘以被驱动表的索引消耗,这里面有一个前提,就是驱动表里面没有加条件,如果驱动表里面他也有条件可以使用到索引的话他也会是一个索引消耗。但这里很明确,他们俩是一个乘积的关系。表连接的数量越多,IO 消耗的代价会更高,所以在可以允许的情况下。尽量控制 join 中的这个表的数量。
-通过使用索引避免排序代价
这也是索引的最重要的用途之一。
二、库表设计规范
1.表结构设计
-降低单条记录长度,提高缓存利用率
单条记录过长,意味着每个 page 下面你存放的记录数就会降低,那缓存利用率自然就会降低。因此要做到就是业务核心表或者业务热点表上面,尽量去降低单行记录的一个长度,可以提升缓存利用率。
-将访问频率低、大字段拆分,用主键关联,提高缓存命中率
尽管刚才提到尽量去避免不必要的那种 join,但是相对来说,大字段访问频度比较低的一些表的一些存在的话,通过就是主键的一个关联,主键的 IO 消耗,按照刚才的这个层高来算,基本上都是在二到四之间,按照主键的 IO 消耗,他提升是相对比较有限的,然后需要大家结合着具体的应用来做。
-适当冗余,不要使用多表 join 查询
-避免数据倾斜(分表策略)
2.索引设计
-选择过滤性高的字段建立索引
判断过滤性高的字段的一个标准 distinct(col)与count(*)比值,通过这个比值来判断他的一个过滤性。
- Join 查询中连接字段建立索引
Join 查询是两表之间是 IO 消耗上的话是一个乘积关系,要去降低它的 IO 消耗,对于被驱表上面建立索引,然后通过索引的使用,然后减少 IO,来让整个 SQL 的 IO有很大幅度的降低。这样可以避免全表扫描。
-尽量使用覆盖索引
覆盖索引是指在非主键设计的时候,把 select 向 select 后面的 select item 相关的列,一起加到非主键索引里面。、避免了在非主键索引里面再有道主键索引表里面的回表操作,这样子的话就是无需访问主键的索引表。然后同时避免随机 IO。
-利用前缀索引
让索引的长度缩短,索引的长度变短,意味着单个page下面存放的索引行数会越多,有助于缓存率和每个page下面能存放的索引的数目。一定要根据具体的业务去明确你的前缀的长度。
name varchar(128),index(name(16))
-避免建重复索引,提高索引使用率
(a) ,(a,b),(a,b,c)
索引并不是建得越多越好,太多的索引会导致写入性能变差。
3.SQL 书写
-建议读写都采用主键索引
-尽量利用索引排序,避免产生临时表
order by col1,col2 index(col1,col2)
-避免对查询字段进行计算(类型转换,计算)(孤立原则)
where id*2>4 >id>2
-避免使用 select*,字段少可配合覆盖索引
-避免使用全模糊查询 like’%xxx%’
Like’%xxx', no
like ‘xxx%’,yes, 可以使用索引
-多 SQL综合考虑,保证核心 SQL
在 SQL 书写上非常关键的是对于这张表来说,访问它的应用会非常多,然后对应着访问他的具体的 SQL 也会很多,所以在索引的设计上的话应该是着重保证核心的SQL 的访问。