设为首页 加入收藏

TOP

取得一张表的数据不在另一张表中的最优秀方法(JOIN与EXISTS的效率研究)
2015-07-24 11:11:05 来源: 作者: 【 】 浏览:1
Tags:取得 张表的 数据 不在 张表中 优秀 方法 JOIN EXISTS 效率 研究

公司有个CRM经纪人管理系统,前天遇到的比较棘手的问题是,要查询一张表中不在另一张表中的所有用户并分页显示,但问题是外表的数据量很大,如果用not in(select ..),not exists(select ...)之类的子查询 的话需要对子查询表进行所有信息的调用过滤才行,一单子查询数据量过大效率问题就来了,于是就私下里查了一点资料,并根据资料中提供的例子建立了对应的测试表做了一些测试,随后将解决问题的方法移交给了技术部的邹鸿同事去解决问题,因为是前天的事情了,本来是事情忙没时间写日志的,就是这个事情没有做个笔记已经两天没睡好觉了,于是乎今天来了还是做一下笔记,分享给大家的好,如果大家有更好的办法 或者 说有bug疑问,请随时Email联系 摘取天上星 happy.yin@qq.com

下面是一组测试的JOIN 、EXISTS 效率对比

先将profiling打开,用来一会查看sql执行时间

set profiling=1;

exists 子查询与 join联接效率的对比

EXPLAIN SELECT film_id, language_id FROM sakila.film
WHERE NOT EXISTS(
    SELECT * FROM sakila.film_actor
    WHERE film_actor.film_id = film.film_id
);

EXPLAIN SELECT film_id, language_id FROM sakila.film
    LEFT JOIN sakila.film_actor USING(film_id)
WHERE film_actor.actor_id IS NULL; 

他们只有一点细微的区别,一个select_type,还有就是Extra里后者用了Not exists,也就是提前终止算法,当遇到第一个actor_id不是null的时候,就舍弃这个筛选.

最后来看看二者的效率

可知使用子查询Exists的效率要低一些.

SELECT DISTINCT film_id FROM sakila.film
    JOIN sakila.film_actor USING(film_id);

SELECT film_id FROM sakila.film
    WHERE EXISTS (
    SELECT * FROM sakila.film_actor
    WHERE film.film_id = film_actor.film_id);

SHOW PROFILES;

可以看出.依然EXISTS效率要低
PS:“摘取天上星” 的小插曲,有人说在使用JOIN方法对 1000万条数据的表进行操作时速度会变得很慢,其实不是SQL语句本身的问题,单表1000万条数据慢的问题是磁盘IO带来的硬伤,是任何优化无法避免的,使用任何软件层优化都无法避免磁盘IO问题对数据库带来的硬伤。。

总结:判断一个表的数据不在另一个表中最优秀方法如下可选(前提条件:a表的id和b表的aid必须有索引,b.aid不能有NULL值):
SELECT aid FROM a LEFT JOIN b ON a.aid = b.aid WHERE b.aid IS NULL LIMIT 0,100;

SELECT DISTINCT aid FROM a JOIN b USING(aid) LIMIT 0,100;

USING用法如下:

用于表连接时给定连接条件(可以理解为简写形式),如

SELECT * FROM a JOIN b ON a.id = b.id;

使用 USING 可以写为

SELECT * FROM a JOIN b USING(id);

?

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇分析HWM 下一篇机器学习___ELM

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·数据库:推荐几款 Re (2025-12-25 12:17:11)
·如何最简单、通俗地 (2025-12-25 12:17:09)
·什么是Redis?为什么 (2025-12-25 12:17:06)
·对于一个想入坑Linux (2025-12-25 11:49:07)
·Linux 怎么读? (2025-12-25 11:49:04)