从驱动表上逐行读取数据,在被驱动表上通过索引匹配数据,假设驱动表N表数据,被驱动表M条数据
Index Nested-Loop Join | Batched Key Access(BKA,NLJ算法的优化) |
---|---|
? 其中N对最终结果影响较大,所以,该算法建议小表作为驱动表
使用BKA优化后,使用批量数据在被驱动表上进行匹配,近似时间复杂度为:
其中K为驱动表分段数,join buffer可能一次性放不下所有数据。如果使用 BKA 优化算的话,设置如下:
-- BKA 算法的优化要依赖于MRR(Multi-Range Read),也需要开启
-- MRR的本质是二级索引获取尽可能多的主键id,经过排序后,在主键索引上顺序查找数据,减少了随机磁盘IO和主键索引访问次数
set optimizer_switch=‘mrr=on,mrr_cost_based=on,batched_key_access=on‘;
注意:上图中如果结果集需要对a进行排序,使用MRR优化,经过排序的主键回表后得到的结果需要进行二次排序,可能得不偿失
把驱动表中数据读入内存join_buffer中,再把被驱动表中每一行数据取出来与join_buffer中数据比对(即使被驱动表上有过滤条件)
从以上两种算法的影响因子来看N对性能影响较大,因此建议小表作为驱动表。更准确地说,在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。
create temporary table …
临时表特点:
alter table temp_t rename to temp_t2
,不能使用rename table temp_t2 to temp_t3
(基于“库名+表名”查找表)应用场景:分库分表系统的跨库查询,例如:将一个大表 ht,按照字段 f,拆分成 1024 个分表,然后分布到 32 个数据库实例上
select v from ht where k >= M order by t_modified desc limit 100;
临时表当前线程可见,为什么写binlog
create table t_normal(id int primary key, c int)engine=innodb;
create temporary table temp_t like t_normal;
insert into temp_t values(1,1);/
insert into t_normal select * from temp_t;
如果binlog_format=statment/mixed,binlog不记录临时表的操作,从库只记录以下语句
create table t_normal(id int primary key, c int)engine=innodb;
insert into t_normal select * from temp_t;
上述两条语句回放, insert into t_normal 的时候,就会报错“表 temp_t 不存在”。因此,需要在binlog中记录临时表的操作,且最后还要写一条drop temporary table
在从库上清除临时表。所以,建议binlog_format=row,因为insert时会记录操作的数据,临时表操作就不需要记录在binlog中
原文:https://www.cnblogs.com/sheung/p/14622666.html