`
宇宙浪子
  • 浏览: 47919 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

in和exists,到底用谁——JAVA伪代码直白分析二者时间复杂度

sql 
阅读更多

引自 http://lazy2009.iteye.com/blog/1697458

 

 

引子

in和exists的讨论从未间断过。之前有“今年是龙年大哥”的有数据有真相的测试博文,现在有程序员老鸟写sql语句的经验之谈上的疯狂讨论。关于exists和in,就是很少人站出来,直白地分析二者本质上的差别,这方面的文章大都是用晦涩的文字表述,或者直接给结论——什么情况下用exists,什么情况下用in,而不给出原理。结果时至今日,还有许多人认为exists一定比in性能高。下面鄙人用JAVA的伪代码,从理论上分析exists和in的时间复杂度

 

 

学生信息表(student_id 学生id, name 学生名称)

student(student_id,name) 

 

学生总分表

score(student_id,total)

 

现在查询出总分(total)超过90分的学生信息。

 

一、粗略的时间复杂度估算

 

1 exists方式

select * from student a where exists (select 1 from score b where b.total>90 and b.student_id = a.student_id);

 

Java代码  收藏代码
  1. List<Map<String,String>> studentList = select * from student ;  
  2. for(i=0;i<studentList.size();i++){  
  3.     String _student_id = studentList.get(i).get("student_id");  
  4.     if(exists("select 1 from score  where total>90 and student_id = " + _student_id )){//建立有索引,这执行很快,O(1)时间  
  5.         studentRow = studentList.get(i)  
  6.         println(studentList.get(i));  
  7.     }  
  8. }  
 

 

时间复杂度为studentList.size() * 1

 

2 in方式

select * from student where student_id in (select student_id from score where total>90);

 

Java代码  收藏代码
  1. List<Map<String,String>> scoreList = select student_id from score where total>90;  
  2. for(i=0;i<scoreList.size();i++){  
  3.     String _student_id = scoreList.get(i).get("student_id ");  
  4.     String studentRow = select * from student where studentId=_student_id;//建立有索引,这执行很快O(1)时间  
  5.     if(null != studentRow {  
  6.         println(studentRow);  
  7.     }  
  8. }  
 

 

时间复杂度为scoreList.size() * 1

 

根据时间复杂度,

exists的耗费的时间,与主表student的记录数成正比,student 表越大,exists耗费时间越长;

in耗费的时间,与子查询的记录数成正比,记录数越多,in耗费时间越长。

 

也就是说,理论上,注意是理论上,

如果子查询的结果集很大,即是scoreList.size()很大,可能就不适合用in。

如果主查询的表记录数很大,即使studentList.size()很大,而子查询的结果很小,可能就不适合用exists。

对比子查询结果集的大小scoreList.size()和主表student表的大小studentList.size(),相信大家能比较简单地对in和exists做出初步选择

 

二、 细致的时间复杂度估算

上面的伪代码是粗略的估算。这里说细致一些。

 

1. 上面的两段伪代码中O(1)时间的部分,因为实际情况中未必使用到索引,所以未必为O(1)。

 

2. exists伪代码的第一句List<Map<String,String>> studentList = select * from student ;必然是全表扫描,算上这一句的,exists伪代码的时间复杂度就是,

studentList.size() * 1+studentTable.size() = 2*studentTable.size().

 

in伪代码的第一句,List<Map<String,String>> scoreList = select student_id from score where score>90;实际情况中,子查询未必是全表扫描。

如果是子查询是全表扫描,那么in的时间复杂度为

scoreList.size() * 1+scoreTable.size() 

如果使用到索引,不是全表扫描,那么in的时间复杂度为

scoreList.size() * 1+ x*scoreTable.size()  (0<=x<=1)

对于x,这样理解。例如本例子中的子查询 (select student_id from score where total>90); 

total上建立上索引,如果只有一个人超过90分,那么x可以视作0

total上建立上索引,如果所有人都超过90分,那么x可以视作1.

 

 

显然,细致分析之后,我们不能很快就下结论孰快孰慢了,索引的情况增加了分析的步骤。特别地,如果in伪代码中每条语句都用到了索引,子查询结果集合很小,另一方面主查询表很大,那么我们可以马上确定用in了。觉得exists一定比in快的同学,现在需要思考下了。

 

三、结论

实际上,一切还是看具体的存储过程以及看测试结果。理论和实际总会有差距,数据量,索引,硬件,ORACLE版本等等都会对结果产生影响。我们要具体问题具体分析。首先,我们可以套用上面两段伪代码去做估算,某些情况下还是可以估算得出来的孰快孰慢。其次,如果数据量大的话,就必须看执行计划,进一步,如果可以的话,就直接执行sql语句查看耗费时间。有时候执行计划还真的对EXISTS,IN有区别对待,这时候估算的思想就要用上。

 

我建议大家不要去纠结in、exists究竟用谁好。数据量不大,in、exists根本无区别,数据量大的时候,你说能不去看看执行计划吗?

 

值得注意的是,据说oracle11g在CBO的情况下,ORACLE会根据数据,对IN,EXISTS做出最佳的选择,而不管你写SQL是IN或者EXISTS。细心想想这也是合理的,IN,EXISTS所表达出的要做的事情是一样的,数据库为什么要区分对待呢?性能的问题交给数据库自己判断好了,不要麻烦开发人员。这也是我建议大家不要纠结in和exists区别的一个原因。

分享到:
评论

相关推荐

    in和exists的区别

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

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

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

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

    在应用目标上,以pgbench_accounts和pgbench_branches为例,我们可以通过四种不同的方式编写查询语句:使用IN子句、使用ANY子句、使用EXISTS子句和使用INNER JOIN。每种方式都有其特点和适用场景。例如,当需要判断...

    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"的区别及执行效率问题,这是一个在数据库操作中非常关键的话题,尤其对于优化查询性能有着不可忽视的作用。下面,我们将深入探讨这两种语句的不同之处及其对执行效率...

    简单的Windows资源管理器——Java版本

    1. **读取文件**:使用`File`类的`exists()`方法检查文件是否存在,`isDirectory()`判断是否为目录,`listFiles()`用于获取目录中的所有文件和子目录。`length()`方法返回文件大小,`getName()`获取文件名。 2. **...

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

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

    java在线查看PDF(csdn)————程序.pdf

    在这个示例代码中,我们将看到如何使用 Java 实现在线查看 PDF 的功能。 标题解释: "java 在线查看PDF(csdn)————程序.pdf" 这个标题表明该代码的主要功能是在线查看 PDF 文件,并且这个示例代码来自 CSDN ...

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

    EXISTS 和 IN 都是 Oracle 中的集合操作符,但它们在使用和执行效率上有所不同。本文将深入探讨 EXISTS 和 IN 的使用场景、执行机制和效率问题。 EXISTS 的使用场景和机制 EXISTS 主要用于判断子查询是否存在记录...

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

    SQL语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句 SQL语句优化是数据库性能优化的重要方面之一。在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用EXISTS...

    SQL里的EXISTS与IN

    在SQL查询语言中,`EXISTS` 和 `IN` 子句都是非常常用且重要的操作符,它们被广泛应用于复杂的查询条件中,特别是当需要检查某个子查询是否返回结果时。根据给定的信息,本文将详细解析`EXISTS`与`IN`的区别以及如何...

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

    ### "Exists"与"In"的效率问题详解 #### 引言 在数据库查询语言SQL中,“Exists”与“In”是两种常用的子查询方法,它们在实际应用中各有优势与局限。本文将深入探讨这两种方法的工作原理、应用场景以及性能差异,...

    sql case when exists not exists in not in

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

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

    - 在某些情况下,可以考虑使用 `EXISTS` 或 `NOT EXISTS` 来替代 `IN` 和 `NOT IN`,以提高查询效率。 #### 三、左连接、右连接与全连接 除了上述几种查询方式之外,SQL 还提供了不同的连接类型来处理不同情况下...

    Oracle In和exists not in和not exists的比较分析

    在Oracle数据库中,`IN`、`EXISTS`、`NOT IN` 和 `NOT EXISTS` 是四个常用的子查询操作符,它们在SQL查询语句中扮演着不同的角色,且各有其性能特点。以下是对这些操作符的详细分析和比较。 1. `IN` 操作符: `IN` ...

    东南大学操作系统实验——实现LRU算法及其近似算法

    时间复杂度方面,LRU算法通常表现为O(1),因为查找、插入和删除操作都在平均情况下具有常数时间复杂度。空间复杂度取决于缓存的最大大小,即`_max_size`。实现难度在于如何有效地维护页面的访问顺序和页面映射。 ...

    简述Oracle中in和exists的不同

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

Global site tag (gtag.js) - Google Analytics