美文网首页
34讲到底可不可以使用join

34讲到底可不可以使用join

作者: carlclone | 来源:发表于2019-06-27 19:34 被阅读0次

    1 两个问题
    我们DBA不让使用join,使用join有什么问题呢?
    如果有两个大小不同的表做join,应该用哪个表做驱动表呢?
    2.案例表

    CREATE TABLE `t2` (
      `id` int(11) NOT NULL,
      `a` int(11) DEFAULT NULL,
      `b` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `a` (`a`)
    ) ENGINE=InnoDB;
    
    drop procedure idata;
    delimiter ;;
    create procedure idata()
    begin
      declare i int;
      set i=1;
      while(i<=1000)do
        insert into t2 values(i, i, i);
        set i=i+1;
      end while;
    end;;
    delimiter ;
    call idata();
    
    create table t1 like t2;
    insert into t1 (select * from t2 where id<=100)
    

    3.straight_join 固定连接方式和驱动表
    如select * from t1 straight_join t2 on (t1.a=t2.a); , t1是驱动表

    执行过程 伪代码 , 假设t2没有索引a , 扫描 100*1000行
    for t1 as row1
    for t2 as row2
    if row1.a==row2.a
    res[ ]=row1.row2

    return res

    有索引a , 扫描了200行,执行一条语句
    for t1 as row1
    primaryID= search in b+tree where key=row1.a
    if primaryID exist
    row2 = retrieve from primarykey index
    res[]=row1.row2

    return res

    4.不使用join 的话 , 则是对row1每条语句执行一次select 等值查询 , 扫描了200行 , 但执行了101条语句
    5.驱动表是走全表扫的 , 被驱动是走b+ 树查找的 , 因此应该用小表做驱动表
    6 复杂度分析 扫描驱动表的N行的复杂度 + 到被驱动表查找的复杂度 N*2logM (需要回表 , 所以是2logM , 查两棵树 ) , 这个复杂度分析不是很懂 , 为什么不是n2logm , 而是n+n2logm ?
    7 结论
    使用join语句,性能比强行拆成多个单表执行SQL语句的性能要好;如果使用join语句的话,需要让小表做驱动表。8 上面的是Indexed NLJ , 使用了索引的NLJ
    9 Simple NLJ 就是没有索引的NLJ
    10 Block NLJ 是 mysql对Simple NLJ做的优化
    11 BNLJ的执行过程:
    把t1的数据读入线程内存的join_buffer中
    扫描t2表 , ……………

    select * from t1 straight_join t2 on (t1.a=t2.b);
    伪代码:
    join_buffer = read t1 data from disk index
    for t2 as row1
    for join_buffer as row2
    if row1.b=row2.a
    res[ ] = row1.row2
    return res

    和Simple NLJ的不同就是内层的10万次遍历判断是在内存中的 , 速度和性能快很多 , S NLJ则是从磁盘一个一个取

    12 如果你的join语句很慢,就把join_buffer_size改大

    13 画图分析BNLJ和INLJ的过程

    14 为什么小表做驱动表速度快? N+N2logm , N小则快 , BNLJ的情况下小表更容易塞进join_buffer_size , 不需要分成更多段 , 导致被驱动表多次被全表扫描

    15 结论
    如果可以使用被驱动表的索引,join语句还是有其优势的;
    不能使用被驱动表的索引,只能使用Block Nested-Loop Join算法,这样的语句就尽量不要使用;
    在使用join的时候,应该让小表做驱动表。
    16 思考题
    我们在上文说到,使用Block Nested-Loop Join算法,可能会因为join_buffer不够大,需要对被驱动表做多次全表扫描。
    我的问题是,如果被驱动表是一个大表,并且是一个冷数据表,除了查询过程中可能会导致IO压力大以外,你觉得对这个MySQL服务还有什么更严重的影响吗?(这个问题需要结合上一篇文章的知识点)

    17 驱动表不是外层和内层循环的简单判断
    18 小表的定义是什么
    在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与join的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。

    相关文章

      网友评论

          本文标题:34讲到底可不可以使用join

          本文链接:https://www.haomeiwen.com/subject/fkrdcctx.html