对性能影响比较大的是SQL的扫描行数和与MYSQL交互次数
NLJ过程
被驱动表的索引可以被用上
select * from t1 straight_join t2 on (t1.a=t2.a);
t1和t2表a字段都有索引,执行过程如下,这里的扫描指的是引擎从磁盘读取记录数据
1.从t1表读取一行(执行器调用引擎接口?),扫描了一行
2.取出这行的a字段,到t2表树搜索取出t2符合条件的行(执行器调用引擎接口?)跟t1读的行组成一行,作为结果集的一部分,扫描了一行
3.重复上面的过程直到t1读完
BLJ流程
被驱动表上没有可用的索引的情况下会使用。
select * from t1 straight_join t2 on (t1.a=t2.b);
t2表b字段没有索引,执行顺序如下
扫描表 t1,顺序读取数据行放入 join_buffer 中,放到 join_buffer 满,(执行器调用引擎?)继续第 2 步;
扫描表 t2,把 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回(执行器调用引擎?);
清空 join_buffer;继续扫描表 t1,顺序读取放入 join_buffer 中,继续执行第 2 步。
BNL和SNL从时间复杂度上看是一样的,但是BNL都是内存判断操作,性能更好。SLJ模式和引擎交互次数多,得多次从磁盘读取数据,而BNJ模式只需要读取一次。速度快上很多,性能也好。
BNL的join_buffer放不下了,就分段放。
BNL也应该让小表做驱动表,减少扫描行数。
问题
1.扫描行和扫描索引有什么不同 ?
2.什么是驱动表和被驱动表?
驱动表是主动发起查询的表,被驱动表是根据on条件被动查询的表
3.straight_join的使用场景?
用于内连接,即返回两个表的交集部分。强制使用左边的表作为被驱动表。而left join和right join已经确定了驱动表。
4.单表使用二级索引范围查询,执行器和引擎交互的次数是多少次 ?比如select * from t1 where a > 2 and a < 100,a是二级索引?单表使用二级索引查询的过程是什么样子的 ?
5.mysql搜索一棵树的时间复杂度是多少?
每次搜索一棵树近似复杂度是以 2 为底的 N的对数。所有的节点都在磁盘里,读盘的次数是树的层高。数据读出来是有序的,有序数组用二分法做搜索时间复杂度是log2N。
6. 使用join的前提是用上索引。举的反面例子是把join拆成循环里面使用SQL查询(多次网络IO代价高),如果拆成的语句使用的是in范围查询用得上索引并且只需要一次网络IO,差别还有那么大吗?个人感觉没有。
7. 可以使用join语句吗?怎么使用
如果可以用上被驱动表的索引,可以走树搜索找到对应的行(总比全表扫描强),是可以使用的。比最傻的循环里SQL查询,多次网络IO好。小表当驱动表,驱动表的大小对扫描行数的影响更大。
8.BNL怎么优化?
下面的措施都是减少扫描行数的。
(1)小表当驱动表。
(2)增大join_buffer
9.如何判断要不要使用join?
如果explain的结果里Extra字段为BNL则不要使用
10.什么是小表?
在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。
11.请求响应慢有什么影响?
大部分请求会阻塞