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
执行时间:
0.032秒
结论:内表大,外表小,速度快。
第二组 内表小 外表大
用例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
分享到:
相关推荐
在Oracle数据库中,"IN"和"EXISTS"都是用于查询某个集合的元素是否存在于另一个集合中的关键字。然而,它们在处理数据时的效率和适用场景有所不同,这主要取决于涉及的数据量以及表之间的关联。 首先,让我们来看看...
IN、EXISTS、NOT IN、NOT EXISTS 是 SQL 中四种常用的条件判断运算符,它们之间的区别主要体现在使用场景、执行效率和语法结构上。 IN IN 是一种条件判断运算符,用于判断某个值是否存在于一个列表中。其基本语法...
标题和描述均聚焦于SQL查询语句中"IN"与"EXISTS"的区别及执行效率问题,这是一个在数据库操作中非常关键的话题,尤其对于优化查询性能有着不可忽视的作用。下面,我们将深入探讨这两种语句的不同之处及其对执行效率...
在实际应用中,选择`IN`还是`EXISTS`应基于对数据特性和查询需求的深入了解。对于小的结果集和简单的查询条件,`IN`可能是更直观的选择。但在处理大数据量和复杂的查询逻辑时,`EXISTS`通常能提供更佳的性能表现。...
Oracle 中 EXISTS 和 IN 的效率问题详解 EXISTS 和 IN 都是 Oracle 中的集合操作符,但它们在使用和执行效率上有所不同。本文将深入探讨 EXISTS 和 IN 的使用场景、执行机制和效率问题。 EXISTS 的使用场景和机制 ...
根据给定的信息,本文将详细解析`EXISTS`与`IN`的区别以及如何在SQL优化过程中将`IN`转换为`EXISTS`来提高查询性能。 ### SQL优化需求背景 在系统开发与维护的过程中,经常会出现SQL查询效率低下、响应时间过长等...
总的来说,在选择使用“Exists”还是“In”时,主要考虑的是内外层查询数据量的对比关系以及查询的具体需求。通过合理选择,可以有效提升SQL查询的执行效率,从而优化应用程序的整体性能。 通过以上详细的分析可以...
基本数据插入 except和intersect和exists和not exists和union和union all sql server
在SQL查询中,`CASE WHEN`、`EXISTS`、`NOT EXISTS`以及`IN`和`NOT IN`是常用的操作符,它们用于处理复杂的条件判断和数据筛选。这些概念对于理解和编写高效的SQL语句至关重要,尤其是在数据分析和数据库管理中。 `...
PostgreSQL作为一种强大的开源关系数据库系统,它支持多种SQL操作,其中包括IN、EXISTS、ANY/ALL和JOIN等操作符。这些操作符在不同的业务场景下有着不同的表现和性能影响。在实际的数据库操作中,选择合适的操作符是...
在查询中,我们可以使用EXISTS和NOT EXISTS来代替IN和NOT IN。例如,我们要查询Sendorder表中的冗余数据(没有和reg_person或worksite相连的数据): ```sql select Sendorder.id, Sendorder.reads, Sendorder....
这是因为`IN`和`NOT IN`需要将主查询中的每一行都与子查询结果进行比较,而`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欢迎下载!
且看接下来的具体分析:in其实是将外表和内表进行hash join,exists是先对外表进行loop操作,然后每次loop后再对内表进行查询。 如果两张表大小差不多,那么exists和in的效率差不多。 例如: 一张大表为A,一张小表B...
- 效率:在某些情况下,`EXISTS` 和 `NOT EXISTS` 可能会提供相似的性能,但通常 `IN` 和 `NOT IN` 比较操作符在处理大量数据时更有效。然而,当涉及到子查询时,`EXISTS` 和 `NOT EXISTS` 可能更合适,因为它们只...
in与exists之争(11g).sql
exists 和 not exists的详细解释