1. 程式人生 > >Mysql5.7 in,exists,表直接關聯效能比較

Mysql5.7 in,exists,表直接關聯效能比較

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)