Mysql - join 优化

MMR 解决的不是 join 优化,而是回表优化:

  mutil-range read , 正如他的名字一样,优化的是离散范围的读,具体是优化在 主键上离散范围的读

  如果是从辅助索引读取符合条件的 (索引列的值 + 主键列的值),是需要根据主键列的值去读主键索引的行记录的,但是如果从辅助索引得到的主键索引是不连续的 比如 

  辅助索引是 (A, 1) (A1, 100) (A2, 1000) 

  因为回表是一行行回的,所以就会产生 离散读取主键索引的情况

  MMR 做的事情是 把得到的 主键先放在 read_rnd_buffer ,然后排序,然后再去主键索引读取 数据行,这样的话就能减少离散读

 

BKA 依赖于 MMR 进行 join 优化:

   Batch Key Access ,正和她的名字一样,是批量的用一堆主键 去 读取主键索引。

   在被驱动表有主键的情况下,驱动表读一行就要去 被驱动表通过主键在B+树查找一次,如果可以一次性给许多 主键,并且是有序的话,就能大大提高效率

   BKA 用上了 NLJ( index nested loop join)情况下用不上的 join buffer,每读一行驱动表,就将连接字段放入 join buffer

  然后将 join buffer 传给 MMR ,MMR 负责 去连接字段对应的被驱动表的辅助索引上读取主键,并且放到 read_rnd_buffer ,然后排序,再去被驱动表的主键索引读取行数据

 

大表 join 对内存的影响:

  如果被驱动表是 大表,驱动表也比较大,能被分成几个 join buffer,那么被驱动表这张大表将被扫描多次

  Buffer Pool 的内存页的缓存机制是 前 8/5 是young 区域,后 8/3 是 old 区域,内存页 LRU 淘汰机制下,新读入的内存页不会马上到 young 区的头部,因为不能保证这个内存页确实是 热数据

  所以只能把他放到 old 的头,如果被驱动表是大表,8/3放得下的话没问题,但是如果放不下,则会挤掉 young 区,如果 young 有热点数据也会被挤掉

  那么热点数据会受影响

  

 解决方法:创建临时表,将需要满足条件的 行从被驱动表选出来。用临时表作为被驱动表

posted @ 2020-11-30 14:08  执生  阅读(152)  评论(0编辑  收藏  举报