Mysql优化原则_小表驱动大表IN和EXISTS的合理利用

//假设一个for循环for($i = 0; $i < 10000; $i++) {     for ($j = 0; $i < 50; $j++)     {

}}

for($i = 0; $i < 50; $i++) {    for ($j = 0; $i < 10000; $j++)    {

}}

看以上两个for循环,总共循环的次数是一样的。但是对于mysql数据库而言,并不是这样了,我们尽量选择第②个for循环,也就是小表驱动大表。
数据库最伤神的就是跟程序链接释放,第一个建立了10000次链接,第二个建立了50次。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。
这时候就诞生了in 和exists的对比。

小表驱动大表:即小的数据集驱动大的数据集。

这里假设A表代表员工表,B表代表部门表。
假设部门只有三个,销售、技术部、行政部,言下之意是在这三个部门里的所有员工都查出。

select * from A where id in (select id from B);

这样写就等价于:
for select id from B。比如华为有100个部门,但是华为的员工少说有15W-20W,员工总比部门多,这时候就相当于得到了小表(部门表);for select * from A where A.id = B.id,相当于A.id等B表里面的,相当于从部门表获得对应的id。

当B表的数据集必须小于A表的数据集时,用in优于exists。
反之

select * from A where exists (select 1 from B where B.id = A.id); //这里的select 1并不绝对,可以写为select ‘X‘或者‘A‘,‘B‘,‘C‘都可以,只要是常量就可以。

这样写就等价于:
for select * from A,先从A表做循环
for select * from B where B.id = A.id,再从B表做循环。
这样exists就会变成看看A表是否存在于(select 1 from B where B.id = A.id)里面,这个查询返回的是TRUE或者FALSE的BOOL值,简单来说就是要当A表的数据集小于B表的数据集时,用exists优于in。要注意的是:A表与B表的ID字段应该建立索引。

语法:EXISTS
SELECT ...FROM table WHERE EXISTS(subquery)。
理解:将主查询的数据放到子查询中做条件验证,根据验证结果(TRUE或者FALSE)来决定朱查询的数据结果是否得意保留。
相当于从表A和B中取出交集,然后再从A表中取出所在交集的部分数据,当然后面加WHERE条件还可以进一步筛选。
补充:
1:EXISTS(subquery)只返回TRUE或者FALSE,因此子查询中的SELECT * 也可以是SELECT 1或者SELECT ‘X‘,官方说法是实际执行时会忽略SELECT清单,因此没有区别。
2:EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担忧效率问题,可进行实际校验。
3:EXISTS子查询旺旺可以用条件表达式,其他子查询或者JOIN来替代,何种最优需要具体问题具体分析。

如果查询的两个表大小相当,那么用in和exists差别不大。

延伸举例巩固:

如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
例如:表A(小表),表B(大表)

select * from A where cc in (select cc from B) ;//  效率低,用到了A表上cc列的索引;select * from A where exists(select cc from B where cc=A.cc) ;// 效率高,用到了B表上cc列的索引。 

相反的

select * from B where cc in (select cc from A) ; //效率高,用到了B表上cc列的索引;select * from B where exists(select cc from A where cc=B.cc) ;//效率低,用到了A表上cc列的索引。

not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

原文地址:https://www.cnblogs.com/jpfss/p/9167153.html

时间: 2024-10-02 09:08:48

Mysql优化原则_小表驱动大表IN和EXISTS的合理利用的相关文章

查询优化--小表驱动大表(In,Exists区别)

Mysql 系列文章主页 =============== 本文将以真实例子来讲解小表驱动大表(In,Exists区别) 1 准备数据 1.1 创建表.函数.存储过程 参照  这篇(调用函数和存储过程批量插入数据)  文章中的第 1-7 步,注意,不要执行第8步 1.2 插入数据 现在来执行第8步. 1.2.1 向 Department 表中插入 100 条记录 CALL insert_dept(1000, 100) 1.2.2 向 Employee 表中插入 100000 条记录 CALL in

小表驱动大表, 兼论exists和in

给出两个表,A和B,A和B表的数据量, 当A小于B时,用exists select * from A where exists (select * from B where A.id=B.id) exists的实现,相当于外表循环,每次循环对内表进行查询? for i in A for j in B if j.id == i.id then .... 相反,如果A大于B的时候,则用in select * from A where id in (select id from B) 这种在逻辑上类似

hive join 优化 --小表join大表

1.小.大表 join 在小表和大表进行join时,将小表放在前边,效率会高,hive会将小表进行缓存. 2.mapjoin 使用mapjoin将小表放入内存,在map端和大表逐一匹配,从而省去reduce. 例子: select /*+MAPJOIN(b)*/ a.a1,a.a2,b.b2 from tablea a JOIN tableb b ON a.a1=b.b1 在0.7版本后,也可以用配置来自动优化 set hive.auto.convert.join=true;

大数据开发实战:Hive优化实战3-大表join大表优化

5.大表join大表优化 如果Hive优化实战2中mapjoin中小表dim_seller很大呢?比如超过了1GB大小?这种就是大表join大表的问题.首先引入一个具体的问题场景,然后基于此介绍各自优化方案. 5.1.问题场景 问题场景如下: A表为一个汇总表,汇总的是卖家买家最近N天交易汇总信息,即对于每个卖家最近N天,其每个买家共成交了多少单,总金额是多少,假设N取90天,汇总值仅取成交单数.A表的字段有:buyer_id. seller_id.pay_cnt_90day. B表为卖家基本信

【Spark调优】小表join大表数据倾斜解决方案

[使用场景] 对RDD使用join类操作,或者是在Spark SQL中使用join语句时,而且join操作中的一个RDD或表的数据量比较小(例如几百MB或者1~2GB),比较适用此方案.. [解决方案] 小表join大表转为小表broadcast+map大表实现.具体为: 普通的join是会shuffle的,而一旦shuffle,就相当于会将相同key的数据拉取到一个shuffle read task中再进行join,此时就是reduce join,此时如果发生数据倾斜,影响处理性能,而此时恰好

Hive中小表与大表关联(join)的性能分析【转】

Hive中小表与大表关联(join)的性能分析 [转自:http://blog.sina.com.cn/s/blog_6ff05a2c01016j7n.html] 经常看到一些Hive优化的建议中说当小表与大表做关联时,把小表写在前面,这样可以使Hive的关联速度更快,提到的原因都是说因为小表可以先放到内存中,然后大表的每条记录再去内存中检测,最终完成关联查询.这样的原因看似合理,但是仔细推敲,又站不住脚跟. 多小的表算小表?如果所谓的小表在内存中放不下怎么办?我用2个只有几条记录的表做关联查询

【Spark调优】大表join大表,少数key导致数据倾斜解决方案

[使用场景] 两个RDD进行join的时候,如果数据量都比较大,那么此时可以sample看下两个RDD中的key分布情况.如果出现数据倾斜,是因为其中某一个RDD中的少数几个key的数据量过大,而另一个RDD中的所有key都分布比较均匀,此时可以考虑采用本解决方案. [解决方案] 对有数据倾斜那个RDD,使用sample算子采样出一份样本,统计下每个key的数量,看看导致数据倾斜数据量最大的是哪几个key. 然后将这几个key对应的数据从原来的RDD中拆分出来,形成一个单独的RDD,并给每个ke

Mysql 优化原则

二.原则总结 原则1.仅列出需要查询的字段,这对速度不会明显的影响,主要是考虑节省应用程序服务器的内存. 原来语句: select * from admin 优化为: select admin_id,admin_name,admin_password from admin 原则2.尽量避免在列上做运算,这样导致索引失效. 原语句: select * from admin where year(admin_time)>2014 优化为: select * from admin where admi

「mysql优化专题」你们要的多表查询优化来啦!请查收(4)

一.多表查询连接的选择: 相信这内连接,左连接什么的大家都比较熟悉了,当然还有左外连接什么的,基本用不上我就不贴出来了.这图只是让大家回忆一下,各种连接查询. 然后要告诉大家的是,需要根据查询的情况,想好使用哪种连接方式效率更高.(这是技术文) 二.MySQL的JOIN实现原理 在MySQL 中,只有一种Join 算法,就是大名鼎鼎的Nested Loop Join,他没有其他很多数据库所提供的Hash Join,也没有Sort Merge Join.顾名思义,Nested Loop Join