到底可不可以用jion?jion如何优化?
前言
jion其实是可以使用的 但是一定要选择小表作为驱动表。
到底可不可以用jion?jion如何优化?
- 前言
- jion的执行过程涉及到两个算法
- 一个是simple nested
- 另一个算法是Black nested
- jion语句优化
- MRR优化
- 如果一个查询,被驱动表很大且都是冷数据,那么会导致什么问题呢?
jion的执行过程涉及到两个算法
一个是simple nested
A表有N行,B表有M行
假设是 dbA jion dbB on dbA.a =dbB.a
如果在B表的a字段上有索引,那么执行流程就是,扫描B表,然后扫描B表的索引拿到结果,在索引上找到一个数据基本是log2的
扫描行数为 N+Nlog2的M次方。
因此驱动表越小 效率越高。
如果没有索引的话 就需要MN次查询了。
另一个算法是Black nested
如果NM 很大。MySQL并不会这么运行,而是使用Black nested 。
执行流程是,先把A表的数据放到jion_buffer中,然后取出B表数据做一一对比。
这个过程在内存中效率会高一些。
如果jion_buffer_size设置大小不够放下A表。就会分多次x对比。这样多等值对比的次数还是NM
但是需要扫描B表x次。
x与N呈现正相关。
因此总数为N+N的某种正相关*M
因此也是小表做驱动表更快。
jion语句优化
MRR优化
首先理解MRR优化,就是虽然在普通索引上去主键索引上查找的时候是一个一个查询的。
但是如果查询之间是有顺序的,那么也会加快查询,
因此如果在查询之前添加了一个排序,一般主键索引都是单调递增的。
所以排序之后,可以更快的查询。
利用这个思想:jion查询时simple nested 可以将驱动表的结构排序之后,再到被驱动表里查询会加快查询。这种方式称为ack。
那么对于black nested如何优化呢,就是变成ack,通过加索引或者改造sql或者通过业务侧分开查询创建hash来实现。
如果一个查询,被驱动表很大且都是冷数据,那么会导致什么问题呢?
-
会有大量io操作,影响性能
-
会导致buffer_pool失效,因为如果3/8分区时,jion之后被驱动表可能会在一秒内进行多次扫描,导致冷数据替换掉了3的部分,导致整个缓存命中率下降。
-
进行N*M次对比,占用cpu资源。