闽公网安备 35020302035485号
SELECT * FROM user u LEFT JOIN class c ON u.id = c.user_id我们来看一下当进行 join 操作时,mysql是如何工作的:

SELECT * FROM user u LEFT JOIN class c ON u.id = c.user_id
因为每次从驱动表取一条数据都是磁盘扫描所有比较耗时。这里就做了优化就是每次从驱动表取一批数据放到内存中,然后对这一批数据进行匹配操作。这批数据匹配完毕,再从驱动表中取一批数据放到内存中,直到驱动表的数据全都匹配完毕。这块内存在MySQL中有一个专有的名词,叫做 join buffer,我们可以执行如下语句查看 join buffer 的大小
show variables like '%join_buffer%'

SELECT a.col3 FROM a JOIN b ON a.col1 = b.col2 WHERE a.col2 > 0 AND b.col2 = 0上述SQL语句的驱动表是a,被驱动表是b,那么存放在Join Buffer中的列是所有参与查询的列,在这里就是(a.col1,a.col2,a.col3)。也就是说查询的字段越少,Join Buffer可以存的记录也就越多!变量join_buffer_size的默认值是256K,显然对于稍复杂的SQL是不够用的。好在这个是会话级别的变量,可以在执行前进行扩展。建议在会话级别进行设置,而不是全局设置,因为很难给一个通用值去衡量。另外,这个内存是会话级别分配的,如果设置不好容易导致因无法分配内存而导致的宕机问题。
-- 调整到1M set session join_buffer_size = 1024 * 1024 * 1024; -- 再执行查询 SELECT a.col3 FROM a JOIN b ON a.col1 = b.col2 WHERE a.col2 > 0 AND b.col2 = 0

-- 表1 a字段加索引 b字段没加 CREATE TABLE `t1` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `a` int DEFAULT NULL COMMENT '字段a', `b` int DEFAULT NULL COMMENT '字段b', PRIMARY KEY (`id`), KEY `idx_a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 表2 create table t2 like t1; -- t1插入10000条数据 t2插入100条数据 drop procedure if exists insert_data; delimiter ;; create procedure insert_data() begin declare i int; set i = 1; while ( i <= 10000 ) do insert into t1(a,b) values(i,i); set i = i + 1; end while; set i = 1; while ( i <= 100) do insert into t2(a,b) values(i,i); set i = i + 1; end while; end;; delimiter ; call insert_data();
-- b字段没有索引 explain select t2.* from t1 inner join t2 on t1.b= t2.b; -- 执行结果 +----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+----------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+----------------------------------------------------+ | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 100 | 100.00 | NULL | | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 10337 | 10.00 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+----------------------------------------------------+从执行计划我们可以得出一些结论:
.返回满足join 条件的数据
-- a字段有索引 EXPLAIN select * from t1 inner join t2 on t1.a= t2.a;执行结果
