`
jinnianshilongnian
  • 浏览: 21513905 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2420516
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3010259
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5640608
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:260219
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597953
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250370
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5860615
Group-logo
跟我学Nginx+Lua开...
浏览量:702889
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785757
社区版块
存档分类
最新评论

in 和 exists的区别 用数据说话

    博客分类:
  • db
阅读更多


1、环境

操作系统:winxp系统 cpu:p8700 双核2.53 内存:2GB 数据库:oracle9i

 

2、表结构

 

sql代码:
drop table base_customer;

create table base_customer
(
   uuid                 number(10) not null,
   customerId           varchar(20),
   showName             varchar(30),
   trueName             varchar(30),
   image                varchar(100),
   pwd                  varchar(50),
   registerTime         timestamp,
   securityKey          varchar(10),
   primary key (uuid),
   unique(customerId)
);

create index idx_customer_registerTime on base_customer(registerTime);

drop table base_customer_sign;
create table base_customer_sign
(
   uuid                  number(10) not null,
   signCustomerUuid       number(10) not null,
   signTime              timestamp not null,
   signCount             number(10) not null,
   signSequenceCount     number(10) not null,
   primary key (uuid)
);
create index idx_sign on base_customer_sign(signCustomerUuid);

 

3、索引及数据量

 

sql代码:
base_customer      100w条
  uuid主键
  customerId 唯一索引
base_customer_sign 100条
  uuid主键
  signCustomerUuid 非唯一索引

 

4、初始化数据用例

 

java代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.util.Date;

import oracle.jdbc.OracleDriver;

public class Test {
	
	
	public static void main(String[] args) throws Exception {
		initData();
	}
	
	public static void initData() throws Exception {
		DriverManager.registerDriver(new OracleDriver());
		Connection conn = null;
		try {
			String url = "jdbc:oracle:thin:@localhost:1521:orcl2";
			String username = "test";
			String password = "test";
			conn = DriverManager.getConnection(url, username, password);
			conn.setAutoCommit(false);
			
			conn.createStatement().execute("truncate table base_customer");
			
			PreparedStatement psst = conn.prepareStatement("insert into base_customer values(?,?,?,?,?,?,?,?)");

			for(int i=1; i<=1000000;i++) {//100w
				int count = 1;
				psst.setInt(count++, i);
				psst.setString(count++, "user" + i);
				psst.setString(count++, "user" + i);
				psst.setString(count++, "user" + i);
				psst.setString(count++, "user" + i);
				psst.setString(count++, "user" + i);
				psst.setTimestamp(count++, new Timestamp(System.currentTimeMillis()));
				psst.setString(count++, "key" + i);
			    psst.addBatch();
			    psst.executeBatch();
			    conn.commit();
			}
			
			PreparedStatement psst2 = conn.prepareStatement("insert into base_customer_sign values(?,?,?,?,?)");

			for(int i=1; i<=0;i++) {//100
				int count = 1;
				psst2.setInt(count++, i);
				psst2.setInt(count++, i);
				psst2.setTimestamp(count++, new Timestamp(System.currentTimeMillis()));
				psst2.setInt(count++, 1);
				psst2.setInt(count++, 1);
				psst2.addBatch();
				psst2.executeBatch();
			    conn.commit();
			}
		    
			psst.close();
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			conn.rollback();
			
		} finally {
			conn.close();
		}
	}

}

 

 

5、场景

 

5.1、第一组 内表大 外表小

 

 

用例1、

 

sql代码:
select count(*) from base_customer_sign where signCustomerUuid in (select uuid from base_customer where trueName like 'user%')

 

执行计划:

如图1-1


执行时间:

   0.015

结论:数据库执行了优化,根本不是我们需要的用例。

 


用例2

 

java代码:
select count(*) from base_customer_sign where signCustomerUuid in (select uuid from base_customer where trueName like 'user%' group by uuid)

执行计划:

如图1-2


执行时间:

   28.672

结论:内表如果查询回来很多数据并要排序的话,效率很极低,因此内表适合返回数据量小的表,例外是用例1场景。

 

 

 

用例3


java代码:
select count(*) from base_customer_sign
where exists (select 1 from base_customer where trueName like 'user%' and base_customer.uuid = base_customer_sign.signCustomerUuid)
 



执行计划:

如图1-3


执行时间:

   0.016

结论:外表执行全扫描,如果外表大很降低效率。

 

用例4

 

java代码:
select count(*) from base_customer_sign where signCustomerUuid in (select uuid from base_customer where customerId like 'user%')

 

执行计划:

如图1-4


执行时间:

   13.61

结论:即使内表很小,但外表数据量很大 同样是低效。

 

用例5

 

java代码:
select count(*) from base_customer_sign
where exists (select 1 from base_customer where base_customer.customerId like 'user%' and base_customer.uuid = base_customer_sign.signCustomerUuid)

 

执行计划:

 

如图1-5


执行时间:

   0032

结论:内表大,外表小,速度快。

 

 

 

 

第二组 内表小 外表大

 

用例6

 

java代码:
select * from base_customer where uuid in (select signCustomerUuid from base_customer_sign where trueName like 'user%')

 

执行计划:

如图1-6


执行时间:

   3.844

结论:外表全扫描,慢。

 

 

用例7


java代码:
select count(*) from base_customer
where exists (select 1 from base_customer_sign where trueName like 'user%' and base_customer.uuid = base_customer_sign.signCustomerUuid)
 



执行计划:

如图1-7


执行时间:

   3.828

结论:和用例6一样。

 

 

 

用例8

 

java代码:
select count(*) from base_customer where uuid in (select signCustomerUuid from base_customer_sign where uuid>1 and signSequenceCount < 1)

 

执行计划:

如图1-8


执行时间:

   0.031

结论:sql被优化,使用base_customer_sign作为外表,而且和内表是通过连接搞定,效率快

 

 

用例9

 

java代码:
select count(*) from base_customer
where exists (select 1 from base_customer_sign where base_customer_sign.uuid>1 and base_customer.uuid = base_customer_sign.signCustomerUuid)

 

执行计划:

如图1-9


执行时间:

   3.531

结论:外表全表扫描快不了。

 

 

 

 

总结:

1、 in可能被优化为 连接

2、 in 在未被优化时,外表小,内表大时(要建临时表并排序 耗时) 效率低

3、 exists 外表数据量大,速度肯定慢,,即使是in同样一样,而对于内表数据量多少跟索引有关。

4、 in  exists 在外表返回的数据量很大时也是低效的。

 

因此,,外表(驱动表) 应该都尽可能的小。

 

 

5、 not in 不走索引的,因此不能用

6、 not exists走索引的。

 

 

自己总结,难免有纰漏 本人只测试以上9个简单的用例,复杂场景可能未考虑到,因此在调优时 应该会看执行计划,根据执行计划决定哪个是高效的。

 

http://sishuok.com/forum/posts/list/1154.html

8
5
分享到:
评论
7 楼 IBelieveKDM 2017-06-07  
涛,你的用例4有问题啊,明明外表是小表,in里面是大表,你正好写反,而且这个用例4要说明什么
6 楼 jinnianshilongnian 2012-10-26  
neitnaco 写道
高人,测试插入100W笔记录的写法不科学呀。
if(i%1000 == 0){  
  pst.executeBatch();  
  conn.commit();  
  pst.clearBatch();  
}

呵呵 测试数据没仔细写  
5 楼 neitnaco 2012-10-26  
高人,测试插入100W笔记录的写法不科学呀。
if(i%1000 == 0){  
  pst.executeBatch();  
  conn.commit();  
  pst.clearBatch();  
}
4 楼 jinnianshilongnian 2012-05-10  
xiaoyuqi00 写道
能加入not in, not exists 的分析就更好了!



5、 not in 不走索引的,因此不能用
6、 not exists走索引的。

也就是说not in 应用场景很少 全表扫描
3 楼 xiaoyuqi00 2012-05-10  
能加入not in, not exists 的分析就更好了!
2 楼 jinnianshilongnian 2012-05-06  
飞天奔月 写道
一直  只看到 别人说 not in 不能用

尽量用 exists,


这个文章是实践出来的

有感觉

谢谢 
1 楼 飞天奔月 2012-05-06  
一直  只看到 别人说 not in 不能用

尽量用 exists,


这个文章是实践出来的

有感觉

相关推荐

    in和exists的区别

    在Oracle数据库中,"IN"和"EXISTS"都是用于查询某个集合的元素是否存在于另一个集合中的关键字。然而,它们在处理数据时的效率和适用场景有所不同,这主要取决于涉及的数据量以及表之间的关联。 首先,让我们来看看...

    sql in,exists,not in,not exists区别

    IN、EXISTS、NOT IN、NOT EXISTS 是 SQL 中四种常用的条件判断运算符,它们之间的区别主要体现在使用场景、执行效率和语法结构上。 IN IN 是一种条件判断运算符,用于判断某个值是否存在于一个列表中。其基本语法...

    in和exists的区别与执行效率问题解析

    标题和描述均聚焦于SQL查询语句中"IN"与"EXISTS"的区别及执行效率问题,这是一个在数据库操作中非常关键的话题,尤其对于优化查询性能有着不可忽视的作用。下面,我们将深入探讨这两种语句的不同之处及其对执行效率...

    in和exists性能解析

    在实际应用中,选择`IN`还是`EXISTS`应基于对数据特性和查询需求的深入了解。对于小的结果集和简单的查询条件,`IN`可能是更直观的选择。但在处理大数据量和复杂的查询逻辑时,`EXISTS`通常能提供更佳的性能表现。...

    oracle中exists_和in的效率问题详解

    Oracle 中 EXISTS 和 IN 的效率问题详解 EXISTS 和 IN 都是 Oracle 中的集合操作符,但它们在使用和执行效率上有所不同。本文将深入探讨 EXISTS 和 IN 的使用场景、执行机制和效率问题。 EXISTS 的使用场景和机制 ...

    SQL里的EXISTS与IN

    根据给定的信息,本文将详细解析`EXISTS`与`IN`的区别以及如何在SQL优化过程中将`IN`转换为`EXISTS`来提高查询性能。 ### SQL优化需求背景 在系统开发与维护的过程中,经常会出现SQL查询效率低下、响应时间过长等...

    “exists”和“in”的效率问题

    总的来说,在选择使用“Exists”还是“In”时,主要考虑的是内外层查询数据量的对比关系以及查询的具体需求。通过合理选择,可以有效提升SQL查询的执行效率,从而优化应用程序的整体性能。 通过以上详细的分析可以...

    基本数据插入 except和intersect和exists和not exists和union和union all

    基本数据插入 except和intersect和exists和not exists和union和union all sql server

    sql case when exists not exists in not in

    在SQL查询中,`CASE WHEN`、`EXISTS`、`NOT EXISTS`以及`IN`和`NOT IN`是常用的操作符,它们用于处理复杂的条件判断和数据筛选。这些概念对于理解和编写高效的SQL语句至关重要,尤其是在数据分析和数据库管理中。 `...

    PostgreSQL IN vs EXISTS vs ANYALL vs JOIN性能分析

    PostgreSQL作为一种强大的开源关系数据库系统,它支持多种SQL操作,其中包括IN、EXISTS、ANY/ALL和JOIN等操作符。这些操作符在不同的业务场景下有着不同的表现和性能影响。在实际的数据库操作中,选择合适的操作符是...

    sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句

    在查询中,我们可以使用EXISTS和NOT EXISTS来代替IN和NOT IN。例如,我们要查询Sendorder表中的冗余数据(没有和reg_person或worksite相连的数据): ```sql select Sendorder.id, Sendorder.reads, Sendorder....

    sql exists和not exists用法

    这是因为`IN`和`NOT IN`需要将主查询中的每一行都与子查询结果进行比较,而`EXISTS`和`NOT EXISTS`则只需判断子查询是否返回至少一行数据即可,无需获取所有数据行。 **性能对比:** - **IN 和 NOT IN**:需要将主...

    经典SQL查询总结关于Exists,not Exists.in ,not in效率的说明。

    - SQL 查询优化器会根据查询语句和数据的实际状态自动选择最优的执行计划。了解和掌握优化器的工作原理有助于更好地编写高效查询。 ### 总结 通过对比分析 `EXISTS`, `NOT EXISTS`, `IN`, `NOT IN` 以及不同类型...

    SQL语句优化——in,not in,exists,not exists, left join...on博客所需SQL语句.txt

    SQL语句优化——in,not in,exists,not exists, left join...on博客所需SQL语句.txt欢迎下载!

    简述Oracle中in和exists的不同

    且看接下来的具体分析:in其实是将外表和内表进行hash join,exists是先对外表进行loop操作,然后每次loop后再对内表进行查询。 如果两张表大小差不多,那么exists和in的效率差不多。 例如: 一张大表为A,一张小表B...

    EXISTS_和_NOT_EXISTS

    - 效率:在某些情况下,`EXISTS` 和 `NOT EXISTS` 可能会提供相似的性能,但通常 `IN` 和 `NOT IN` 比较操作符在处理大量数据时更有效。然而,当涉及到子查询时,`EXISTS` 和 `NOT EXISTS` 可能更合适,因为它们只...

    in与exists之争(11g).sql

    in与exists之争(11g).sql

    exists 和 not exists的详细解释

    exists 和 not exists的详细解释

Global site tag (gtag.js) - Google Analytics