mysql驱动语句 mysql的连接驱动是什么( 三 )


所以不能单独看表的数据总数据行数来决定谁是驱动表谁是被驱动表 。要看实际参与关联的数据行是多少,还要看实际参与关联查询的字段有哪些,因为有些表虽然有很多的字段,但是我们关联查询的时候,实际上在select后面只用了1个字段,此时在计算参与关联查询的表锁占用的空间大小的时候,把这个表的所有字段都计算进来显示是不合理的 。
而有些观点说只要是在where条件中出现的表,就是驱动表 。显然通过我们上面的实验可以看出这个观点是不正确的 。两条SQL语句,在where条件中都使用了a.id作为过滤条件,但是驱动表却因为过滤行数的不同而出现截然相反的结果 。有些在where条件中没有出现的表,也可能是驱动表 。
所谓的小表是什么表
前面我们提到在inner join中,MySQL会选择小表作为驱动表,那么我们怎么理解这个小表的概念呢?什么样的表算是小表?
这里对于大小的判断,是指真正参与关联查询的数据量所占用的join_buffer的大小来区分的,而不是根据表中所有的数据行数来判断的 。
Demo1:两个表所有的字段类型和大小都相同的前提下,如果一个表有1000万行、10列的数据,但是经过where条件过滤后,只有10行数据参与join操作,而另外一张表有100行、10列数据 。那么此时过滤后的有10行数据参与join操作的表是驱动表,有100行数据参与join操作的表示被驱动表 。所以,我们不能盲目的认为表的数据行数少的表就一定是驱动表、数据行数大的表就一定是被驱动表 。
另外,select关键字后面查询的字段列表也会影响到底谁是驱动表和被驱动表 。
Demo2:一个表A有20个字段、50行数据;另外一个表B有2个字段、50行数据 。两个表中所有的字段的类型全部为char(10) 。我们的查询语句如下:
select a.*, b.code from A as a inner join B as b on a.id = b.id;
此时,表A是被驱动表,表B是驱动表 。因为:查询的字段结果中,A表占用的空间10000比B表占用的空间500要大20倍 。
对于A和B在查询的过程中,它们所占用空间的大小,我们可以采用如下简单的计算过程:
A表的所有字段都参与查询,所以:查询的字段数 * 参与join的行数 * 每个字段的空间大小 = 占用的空间大小,即为:20 * 50 * 10 = 10000B表只有code字段参与查询,同样的计算方式:查询的字段数 * 参与join的行数 * 每个字段的空间大小 = 占用的空间大小,即为:1 * 50 * 10 = 500注意:上面我们在对比A和B两个表在join关联时占用的空间大小的时候,忽略了a.i和b.id
所占用的空间,因为对于A和B来说,他们的行数一样都是50,字段类型也一样都是char(10),两个ID占用的空间也是一样的 。所以,在A和B两者都忽略id字段的情况下,最后判断的结果也是没有问题的 。
综上两个例子,当我们使用inner join的时候,对于哪个表示小表,那个表是大表,需要仔细衡量一下,不能根据表中的数据量直接拍脑袋就直接下结论 。
join buffer的概念
前面我们提到的join查询的时候,会把驱动表中的数据全部查询出来放入到内存中,而这个内存就是我们现在要说的:join buffer,它的大小是有参数join_buffer_size大小来决定的,默认值为262144字节,即为:256KB 。而它所能设置的最小值为128字节,最大值为:4GB1字节 。
对于在多表连接查询的时候,由于纯索引扫描、范围索引扫描和不使用索引因而执行全表扫描的关联查询,join_buffer_size的值的大小定义了一个buffer pool 最小的大小 。
这个值不建议设计的特别大,因为MySQL会为每一个join查询语句都分配一个当前配置的join_buffer_size大小的
join buffer,所以如果这个值配置过大,那么当查询并发量大的时候,可能导致内存被吃掉的很多 。
比较好的建议是保持全局的设置为一个较小的值,然后当我们执行一个比较大的join查询的时候,设置session级别的join_buffer_size比较大,只对当前会话级别的查询生效 。
两个表join执行的过程是怎么样的
对于两个表A和B进行inner join这个join是怎么一个执行过程呢?他们的SQL语句如下:
select * from A as a inner join B as b on a.code = b.code;
我们假设A表是小表也就是驱动表,B表是大表也就是被驱动表 。那么上面这个关联查询是怎么一个关联过程呢?
Index Nested-Loop Join
Index Nested-Loop Join:索引嵌套循环连接 。
我们采用如下SQL来解释Index Nested-Loop Join这种关联查询的执行过程 。
explain select * from A as a inner join B as b on a.id = b.id;
A、B的表结构和查询计划如下图所示:


推荐阅读