mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.9-log |
+-----------+
1 row in set (0.00 sec)
制造数据
DROP TABLE IF EXISTS test;
CREATE TABLE test(
ID INT(10) NOT NULL,
`Name` VARCHAR(20) DEFAULT '' NOT NULL,
PRIMARY KEY( ID )
)ENGINE=INNODB DEFAULT CHARSET utf8;
#创建生成测试数据的存储过程
DROP PROCEDURE IF EXISTS pre_test;
DELIMITER //
CREATE PROCEDURE pre_test()
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
WHILE i<4000000 DO
INSERT INTO test ( ID,`Name` ) VALUES( i, CONCAT( 'Carl', i ) );
SET i = i+1;
IF i%10000 = 0 THEN
COMMIT;
END IF;
END WHILE;
END; //
DELIMITER ;
CREATE TABLE test_bak AS SELECT * FROM test LIMIT 1000;
CREATE INDEX ind_t_id ON test(id);
SHOW CREATE TABLE test;
CREATE INDEX ind_t1_id ON test_bak(id);
方式1:查询出结果0.02s
mysql> EXPLAIN SELECT * FROM test t WHERE t.id IN(SELECT id FROM test_bak) LIMIT 100000;
+----+-------------+----------+------------+-------+---------------+-----------+---------+----------------+------+----------+------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+-------+---------------+-----------+---------+----------------+------+----------+------------------------+
| 1 | SIMPLE | test_bak | NULL | index | ind_t1_id | ind_t1_id | 4 | NULL | 1000 | 100.00 | Using index; LooseScan |
| 1 | SIMPLE | t | NULL | ref | ind_t_id | ind_t_id | 4 | zz.test_bak.ID | 1 | 100.00 | NULL |
+----+-------------+----------+------------+-------+---------------+-----------+---------+----------------+------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)
方式2:查询出结果0.024s
mysql> EXPLAIN SELECT t.* FROM test t ,test_bak t1 WHERE t.id=t1.id LIMIT 100000;
+----+-------------+-------+------------+-------+---------------+-----------+---------+----------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-----------+---------+----------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | index | ind_t1_id | ind_t1_id | 4 | NULL | 1000 | 100.00 | Using index |
| 1 | SIMPLE | t | NULL | ref | ind_t_id | ind_t_id | 4 | zz.t1.ID | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+-----------+---------+----------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
方式2:查询出结果接近100s,查询的速度会随着limit越大变得越大。
mysql> EXPLAIN SELECT t.* FROM test t WHERE EXISTS(SELECT 1 FROM test_bak t1 WHERE t1.id = t.id) LIMIT 100000;
+----+--------------------+-------+------------+------+---------------+-----------+---------+---------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------+------------+------+---------------+-----------+---------+---------+---------+----------+-------------+
| 1 | PRIMARY | t | NULL | ALL | NULL | NULL | NULL | NULL | 3992817 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | t1 | NULL | ref | ind_t1_id | ind_t1_id | 4 | zz.t.ID | 1 | 100.00 | Using index |
+----+--------------------+-------+------------+------+---------------+-----------+---------+---------+---------+----------+-------------+
2 rows in set, 2 warnings (0.00 sec)
+-----------+
| version() |
+-----------+
| 5.7.9-log |
+-----------+
1 row in set (0.00 sec)
制造数据
DROP TABLE IF EXISTS test;
CREATE TABLE test(
ID INT(10) NOT NULL,
`Name` VARCHAR(20) DEFAULT '' NOT NULL,
PRIMARY KEY( ID )
)ENGINE=INNODB DEFAULT CHARSET utf8;
#创建生成测试数据的存储过程
DROP PROCEDURE IF EXISTS pre_test;
DELIMITER //
CREATE PROCEDURE pre_test()
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
WHILE i<4000000 DO
INSERT INTO test ( ID,`Name` ) VALUES( i, CONCAT( 'Carl', i ) );
SET i = i+1;
IF i%10000 = 0 THEN
COMMIT;
END IF;
END WHILE;
END; //
DELIMITER ;
CREATE TABLE test_bak AS SELECT * FROM test LIMIT 1000;
CREATE INDEX ind_t_id ON test(id);
SHOW CREATE TABLE test;
CREATE INDEX ind_t1_id ON test_bak(id);
方式1:查询出结果0.02s
mysql> EXPLAIN SELECT * FROM test t WHERE t.id IN(SELECT id FROM test_bak) LIMIT 100000;
+----+-------------+----------+------------+-------+---------------+-----------+---------+----------------+------+----------+------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+-------+---------------+-----------+---------+----------------+------+----------+------------------------+
| 1 | SIMPLE | test_bak | NULL | index | ind_t1_id | ind_t1_id | 4 | NULL | 1000 | 100.00 | Using index; LooseScan |
| 1 | SIMPLE | t | NULL | ref | ind_t_id | ind_t_id | 4 | zz.test_bak.ID | 1 | 100.00 | NULL |
+----+-------------+----------+------------+-------+---------------+-----------+---------+----------------+------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)
方式2:查询出结果0.024s
mysql> EXPLAIN SELECT t.* FROM test t ,test_bak t1 WHERE t.id=t1.id LIMIT 100000;
+----+-------------+-------+------------+-------+---------------+-----------+---------+----------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-----------+---------+----------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | index | ind_t1_id | ind_t1_id | 4 | NULL | 1000 | 100.00 | Using index |
| 1 | SIMPLE | t | NULL | ref | ind_t_id | ind_t_id | 4 | zz.t1.ID | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+-----------+---------+----------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
方式2:查询出结果接近100s,查询的速度会随着limit越大变得越大。
mysql> EXPLAIN SELECT t.* FROM test t WHERE EXISTS(SELECT 1 FROM test_bak t1 WHERE t1.id = t.id) LIMIT 100000;
+----+--------------------+-------+------------+------+---------------+-----------+---------+---------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------+------------+------+---------------+-----------+---------+---------+---------+----------+-------------+
| 1 | PRIMARY | t | NULL | ALL | NULL | NULL | NULL | NULL | 3992817 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | t1 | NULL | ref | ind_t1_id | ind_t1_id | 4 | zz.t.ID | 1 | 100.00 | Using index |
+----+--------------------+-------+------------+------+---------------+-----------+---------+---------+---------+----------+-------------+
2 rows in set, 2 warnings (0.00 sec)