mysql联接算法

  联接算法是MySQL数据库处理联接的物理策略,目前支持Nested-Loops Join算法,时间复杂度为O(N)有索引,无的话为o(N2).
这个是没有索引的表联接

    For each row r in R do
        For each row s in S do
            If r and s satisfy the join condition
                Then output the tuple 
  然而真实情况mysql没有采用这种算法。是这样的:   把驱动表的要select的数据,丢到join_buffer中内存。再扫描被驱动表,取出一行行数据对比,满足条件的作为结果集返回。和上面的算法比较,比较次数,扫描次数一样,但是是内存,因此效率高很多。显然join_buffer可能不够大,默认是256k,join_buffer_size这个参数确定, 分段处理 ,放满了join_buffer,比较,然后清空join_buffer,再放入驱动表的数据。比较,直到走完。但是分段次数太多,可能导致扫描次数变多。因此,可以将join_buffer这个调大一点。   时间复杂度为o(R*S)   这个是有索引的
    For each row r in R do
        lookup r in S index
            If find s == r
               Then output the tuple 

  对于对于联接的列含有索引的情况,外部表(驱动表,也就是需要全表扫描的表)的每条记录不再需要扫描整张内部表,只需要扫描内部表上的索引即可得到联接的判断结果。
  根据前面描述的Simple Nested-Loops Join算法,优化器在一般情况下总是选择将联接列含有索引的表作为内表。如果两张表R和S在联接列上都有索引,并且索引的高度相同,那么优化器会选择记录数少的表作为外部表,这是因为内部表的扫描次数总是索引的高度,与记录的数量无关。

  如果联接表没有索引时,Simple Nested-Loops Join算法扫描内部表很多次,执行效率会非常差。而Block Nested-Loops Join算法就是针对没有索引的联接情况设计的,其使用Join Buffer(联接缓存)来减少内部循环取表的次数。
  对这个没有太大注意,反正效率不高就是了。最好还是加上索引用第一个最好了。
  对于left join 那么一定是左边的表作为外部表,即使右边表没有索引而自身有索引。
  对于 right join 那么一定是右边的表作为外部表,即使左侧表无索引,而右侧表有索引。

  为了效率:
  1.我们一般左连接,那么希望2表连接的话,小数据量的放到左边。
  2.左连接,左边表字段是否有索引不关心,右边表必须要有索引。
  3.表连接最好加上索引,否则另外一个算法效率很低。
  4.内连接比左右连接方便,是因为内连接可以自身优化左右表的顺序。原则如下:1,若都有索引,默认数据量小的表作为外部表。即时加了索引缩小范围。2,若只有一个表有索引,那么默认没有索引的表作为外部表。3,若都没有索引,那么默认Block Nested-Loops Join算法。
  ps:这里的小表:是指按照各自的条件过滤后,这些判断是要走索引的,不然和全表扫描没区别了。计算参与join的各个字段的总数据量,这个总数据量小的,就是小表。