• 123
    2024-09-25 来自浙江
    老师,请教两个问题: 1、“在分支页面中,Value 存了下一层索引页面的编号(Page No),页面编号就是页面在数据文件中的地址”,其中页面编号就是页面在数据文件中地址,这个数据文件应该就是.ibd文件吧,存储了数据信息,并且一二级索引的数据都在这个文件里面,所在在ibd文件中哪里可以看到页编号,老师后面会讲数据的物理存储结构吗? 2、表数据存储在页中,页中存储行数据,当行数据变大之后,例如可变长VARCHAR字段,则就会进行页的新增,老师文中提到,每个区块由连续的64个数据页组成,这里应该是物理连续吧?那么行内数据增加后务必会造成数据页的分裂,也就是说原来一页能存100条,现在只能存储50条了,同时为了保证连续,多出的页面会造成后续页面在空间上移动,进而造成在磁盘空间中数据的移动,不知道怎么理解对不对,那么为了防止大量的数据移动,区块或者段数据之间应该是逻辑连续而不是物理连续,也就是说使用链表的形式连接?

    作者回复: 问题1:第三章会讲物理存储结构。页面编号在每个页面头部有记录。页面编号可以直接转换为文件中的偏移量:PageNumber * PageSize,PageSize是固定的,默认就是16384。 问题2:每个区块中的64个页面,在文件中是连续的(1M空间),但是对应到磁盘中的扇区,不一定是连续的。 页面分裂时,InnoDB会使用一些方法,尽量让索引页面在文件中相邻,但不保证。 页面分裂时会复制一部分数据到新的页面。同一层中,索引页面逻辑上组成一个双向链表。

    
    
  • 123
    2024-09-25 来自浙江
    思考题: 以下测验均在mysql8.0.29版本中: #符合idx_abc索引的顺序条件,可以通过a,b进行条件筛选,但是需要回表 select * from t_abc where a = 10 and b = 10; #符合idx_abc索引的最左匹配原则,c=10未能使用索引匹配,但可以使用索引条件下推,过滤一些索引行 select * from t_abc where a = 10 and c = 10; #符合idx_abc索引最左匹配,但只能利用a字段过滤,需要回表,再判断d的值,若改成or则不走索引 select * from t_abc where a = 10 and d = 10; 上述三条语句全部走索引,区别在于能利用索引提升的速度不同; #无法利用索引有序性消除排序,因为字段顺序不连续(Using filesort) select * from t_abc where a = 10 order by a,c; #无需额外排序 select * from t_abc where a = 10 order by b,c; #完美匹配idx_abc,走覆盖索引 select id, a, b, c from t_abc where a = 10; 上述两条sql语句区别在于能否通过索引原有的顺序而消除排序; #因为不符合最左匹配原则,应该不走二级索引,但是由于所需字段均在idx_abc中,mysql认为走索引的扫描成本会更低,所以走了索引,扫描行数和下面的全表扫描的行数是一致的,走了覆盖索引(Using index) select id, a, b, c from t_abc where b = 10; #和select * 无异,因为b上面建索引且不符合最左匹配原则,走全表扫描 select id, a, b, c, d from t_abc where b = 10; 上述三条sql区别在于是否可以利用覆盖索引,根据语句的内容选择扫描成本低的方案
    展开

    作者回复: 解读非常全面👍

    
    