NOT IN , NOT EXISTS ,LEFT JOIN / IS NULL 比较

要想从数据库中选出在A表中存在而又在B表中不存在的记录时,哪种方法更适合?

第一种:

SELECT  l.*

FROM    t_left l

LEFT JOIN

t_right r

ON      r.value = l.value

WHERE   r.value IS NULL

第二种:

SELECT  l.*

FROM    t_left l

WHERE   l.value NOT IN

(

SELECT  value

FROM    t_right r

)

第三种:

SELECT  l.*

FROM    t_left l

WHERE   NOT EXISTS

(

SELECT  NULL

FROM    t_right r

WHERE   r.value = l.value

)

首先创建两张表和制造数据:

CREATE TABLE filler (
        id INT NOT NULL PRIMARY KEY AUTO_INCREMENT
) ENGINE=Memory;
 
CREATE TABLE t_left (
        id INT NOT NULL PRIMARY KEY,
        value INT NOT NULL,
        stuffing VARCHAR(200) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
 
CREATE TABLE t_right (
        id INT NOT NULL PRIMARY KEY,
        value INT NOT NULL,
        stuffing VARCHAR(200) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
CREATE INDEX ix_left_value ON t_left (value);
CREATE INDEX ix_right_value ON t_right (value);
DELIMITER $$
CREATE PROCEDURE prc_filler(cnt INT)
BEGIN
        DECLARE _cnt INT;
        SET _cnt = 1;
        WHILE _cnt <= cnt DO
                INSERT
                INTO    filler
                SELECT  _cnt;
                SET _cnt = _cnt + 1;
        END WHILE;
END
$$
 
DELIMITER ;
 
START TRANSACTION;
CALL prc_filler(100000);
COMMIT;
 
INSERT
INTO    t_left
SELECT  id, id % 10000,
        RPAD(CONCAT('Value ', id, ' '), 200, '*')
FROM    filler;
 
INSERT
INTO    t_right
SELECT  (l.id - 1) * 10 + f.id,
        l.value + 1,
        RPAD(CONCAT('Value ', (l.id - 1) * 10 + f.id, ' '), 200, '*')
FROM    (
        SELECT  id
        FROM    filler
        ORDER BY
                id
        LIMIT 10
        ) f
CROSS JOIN
        t_left l;

T_left表计100,000有10,000记录是不同的。

T_right表计1,000,000有10,000记录是不同的。

在t_left表中有10行与t_right表不同。

两张表都建了索引。

第一种方法:执行时间是0.663s

第二种方法:执行时间是0.679s

第三种方法:执行时间是1.796s

 

总结:第一种方法和第二种方法可取,not exists 性能不咋滴。

ps.文章在http://explainextended.com/博文翻译而来!

转载于:https://www.cnblogs.com/tony-jingzhou/archive/2012/02/08/2343315.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值