sql中为什么关联性能会比in 、sqlserver existtt好

新闻资讯 News当前位置: >
使用sql语句提高数据库性能
作者:思科商务 来源:本站 发表时间: 10:18:07&查看:次
为了获得稳定的执行性能,SQL语句越简单越好。对复杂的SQL语句,要设法对之进行简化,本文给大家介绍优化SQL语句提高数据库性能。
现在数据越来越复杂和庞大,很多时候影响程序运行性能不理想的原因中除了一部分是因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化。
一、问题的提出
在项目实际使用中,数据是一个长期累计的过程,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到成千上百倍,因此高质量的SQL语句,更能提高系统的可用性。
二、SQL语句编写注意问题
下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低。
1.&操作符优化
(a) IN&操作符
&在使用中尽量用EXISTS替代IN、用NOT EXISTS替代NOT IN&&。
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,&使用EXISTS(或NOT EXISTS)通常将提高查询的效率。。在子查询中,NOT IN子句将执行一个内部的排序和合并。&无论在哪种情况下,NOT IN都是最低效的&(因为它对子查询中的表执行了一个全表遍历)。。为了避免使用NOT IN&,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS。
(推荐)select* from dt_article where exists(select id from dt_article_category wheredt_article_category。id=dt_article。category_id andtitle='公司新闻')
(不推荐)select* from dt_article where category_id in (select id from dt_article_categorywhere title='公司新闻')
(b) IS NULL&或IS NOT NULL操作(判断字段是否为空)
判断字段是否为空一般是不会应用索引的,因为索引是不索引空值的。不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。&
&&&&例子:
(推荐)select* from dt_article where title&'';
&(不推荐)select* from dt_article where title is null;
(c) &&及&&&操作符(大于或小于操作符)
(推荐)select * from dt_article where id&=101;
(不推荐)select * from dt_article where id&100;
两者的区别在于,&前者将直接跳到第一个id等于101的记录而后者将首先定位到id=100的记录并且向前扫描到第一个id大于100的记录。
(d)LIKE操作符
LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如like '%福瑞希%'这种查询不会引用索引,而like'福瑞希%'则会引用范围索引。
一个实际例子:用dt_article表中内容可来查询,&content&like'%福瑞希%'这个条件会产生全表扫描,如果改成contentlike '福瑞希%'则会利用content的索引进行范围的查询,性能肯定大大提高。
在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。
(e) UNION操作符
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行去重和排序。 假如用UNION ALL替代UNION, 这样排序就不是必要了。 效率就会因此得到提高。 需要注重的是,UNION ALL 将重复输出两个结果集合中相同记录。 因此各位还是要从业务需求分析使用UNIONALL的可行性。 UNION 将对结果集合去重排序,这个操作会使用到SORT_AREA_SIZE这块内存。 对于这块内存的优化也是相当重要的。
我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响。 当查询列碰到”NOT,他就会停止使用索引转而执行全表扫描。
&&& 通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果。 对索引列使用OR将造成全表扫描。 注重, 以上规则只针对多个索引列有效。 假如有column没有被索引, 查询效率可能会因为你没有选择OR而降低。 在下面的例子中, title和category_id上都建有索引。
(推荐)select * from dt_article where title='清洗空气' union all select * from dt_article where category_id=92
(不推荐)select * from dt_article where title='清洗空气' or category_id=92 假如你坚持要用OR, 那就需要返回记录最少的索引列写在最前面。&
&&&&&& 另外在一些情况下,也可以使用IN来替代OR, &&& 这是一条简单易记的规则,但是实际的执行效果还须检验。
(推荐)select * from dt_article where category_id in (89,92)
(不推荐)select * from dt_article where category_id=92 or category_id=89
(h) DISTINCT
&&&& 当提交一个包含一对多表信息的查询时,避免在SELECT子句中使用DISTINCT。 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,马上返回结果。&
2. SQL书写的影响
&(a) WHERE后面的条件顺序影响
WHERE子句后面的条件顺序对大数据量表的查询会产生直接的影响。如:
select * from dt_article where category_id=92 and is_hot=1
select * from dt_article where is_hot=1 and category_id=92
以上两个SQL中category_id(电压等级)及is_hot(销户标志)两个字段都没进行索引,所以执行的时候都是全表扫描,第一条SQL的is_hot=1在记录集内比率为99%,而category_id=92的比率只为1%,在进行第一条SQL的时候99%条记录都进行category_id及is_hot的比较,而在进行第二条SQL的时候1%条记录都进行category_id及is_hot的比较,以此可以得出第二条SQL的CPU占用率明显比第一条低。
WHERE解析是采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。&
3.&更多方面SQL优化资料分享
(1) 选择最有效率的表名顺序(只在基于规则的优化器中有效):
ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersectiontable)作为基础表, 交叉表是指那个被其他表所引用的表.
(2) SELECT子句中避免使用 ‘ * ‘:
ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。
(3) 减少访问数据库的次数:
ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等。
(4) 整合简单,无关联的数据库访问:
如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系) 。
(5) 用TRUNCATE替代DELETE:
当删除表中的记录时,在通常情况下, 回滚段(rollbacksegments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML) 。
(6) 尽量多使用COMMIT:
只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少,COMMIT所释放的资源:
a. 回滚段上用于恢复数据的信息.
b. 被程序语句获得的锁
c. redo log buffer 中的空间
(7) 通过内部函数提高SQL效率:
复杂的SQL往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的。
(8) 使用表的别名(Alias):
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
(9) 总是使用索引的第一个列:
如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。
(10) 避免使用耗费资源的操作:
带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强。
为您保驾护航
上一篇:下一篇:
新闻分类 News Nav
推荐新闻 News
联系我们 Contact Us
全国统一服务热线
我们的邮箱SQL编程中需要注意的几点43
上亿文档资料,等你来发现
SQL编程中需要注意的几点43
SQL编程中需要注意的几点;一、错误;1.对空值(NULL)没有做特殊处理;原因:空值(NULL)不是0或者’’,不能直接判;2.对用户输入的参数不做处理,直接带入到SQL中;原因:用户输入的参数没有做过滤处理;解决方法:用户输入的参数做处理,过滤掉非法字符(;3.使用字段位置来获取数据,导致取数据错误;原因:在记录集中获取数据时使用位置号,在数据表字;4.
SQL编程中需要注意的几点
1. 对空值(NULL)没有做特殊处理。
原因:空值(NULL)不是0或者’’,不能直接判断或做比较,需要做特殊处理。 解决方法:用ISNULL()函数做处理后使用。
2. 对用户输入的参数不做处理,直接带入到SQL中,导致SQL注入。
原因:用户输入的参数没有做过滤处理。
解决方法:用户输入的参数做处理,过滤掉非法字符(/ \ : * ? “ & & | 空格 = ‘ % _ - ! ( )等)和系统关键字(and or not like select del delete insert update等)后再带入到SQL中。
3. 使用字段位置来获取数据,导致取数据错误。
原因:在记录集中获取数据时使用位置号,在数据表字段次序修改时会出错。 解决方法:在记录集中获取数据时使用字段名称。
4. 写入字符串超过字段长度,或者数值溢出。
原因:设计时没有考虑到这么大的数据或长度,使用时超出。
解决方法:字段长度或类型定义足够大,并且写入数据库之前要检查。
5. 自动类型转换错误。
原因:数据库会对不同的字段类型做自动转换,格式可能与想象中不一致,例如时间类型转为字符类型。
解决方法:强制指定转换方式。
6. char和varchar的不同,以及nchar、nvarchar的不同。
原因:char定长,varchar变长;nchar、nvarchar使用UNICODE字符集,长度双倍。 解决方法:根据需要使用不用类型,VC最好不要使用nchar和nvarchar。写入字符之前最好去掉左右两边的空格(根据具体情况)。
7. 返回多条数据记录,导致程序报错。
原因:SQL编写时只考虑到返回一条记录,但是返回了多条。
解决方法1:SQL编写时加上TOP 1,或者ROWNUM=1等限制条件。
解决方法2:SQL编写时嵌套查询不要使用“=”,使用“in”(最好使用exist来代替)。
8. 没有返回数据记录,导致程序报错。
原因:SQL编写时只考虑到能够正常返回记录,但是没有返回记录。
解决方法:SQL执行后,要判断返回记录集的条数,或者用@@rowcount来判断。
9. 应该使用Update时使用Insert,导致出现多条记录。
原因:编写代码时应该使用Update更新,结果使用Insert插入了一条新记录。 解决方法:对只应该有一条记录的数据,要使用Update更新。
10. 多个关联数据操作没有统一提交,导致数据不一致。
原因:同上。
解决方法:使用数据库事务统一进行提交,并且如果失败统一回滚。
11. 不使用触发器,导致数据不一致。
原因:在多张表的数据要同步更新时,使用手工操作从而导致数据不一致。
解决方法:使用触发器进行同步修改
12. 乱使用触发器,导致递归。
原因:触发器修改数据,激活另外的触发器工作,从而导致递归。
解决方法:小心处理,避免一个触发器激活另外一个触发器。
13. 乱用外连接,导致查询出很多相关但是无效的数据。
原因:查询条件中使用外连接LEFT JOIN或者RIGHT JOIN。
解决方法:SQL编写时尽量使用内连接INNER JOIN,如有特殊需要才使用外连接。
14. 对SQL操作是否成功没有做判断,导致程序报错。
原因:同上。
解决方法:编写代码时要对SQL操作是否成功进行判断,对于INSERT、DELETE、UPDATE等操作如果使用事务,失败后还要回滚。
15. 程序中对数据库操作部分没有保护,导致程序非法操作。
原因:数据库操作很有可能失败,如果不保护的话很容易导致非法操作,并且会导致数据库的死锁。
解决方法:对数据库操作部分的代码要捕获异常并处理(程序中的其它部分也应该如此)。
16. 数据库连接使用完后不释放,导致连接大量占用。
原因:同上。
解决方法:数据库连接使用完后立即释放(使用数据库连接池时酌情处理)。
1. 使用SELECT * 而不是使用具体字段名取数据,导致无效数据通讯。
原因:如果一张表有几十个字段,但是只需要用到其中的几个字段。
解决方法:使用具体字段名取数据。
2. 对欲查询的数据进行运算,导致查询速度慢。
原因:对欲查询的数据进行运算,例如SELECT UserName FROM User Where CreateDate+30&’’。
解决方法:改为对查询条件进行运算,例如SELECT UserName FROM User Where CreateDate&’’。
3. 对于频繁使用,并且对准确性要求不高的查询没有显示不加锁。
原因:SQL Server查询语句会默认加共享锁,会导致行、表加锁,阻碍更新、删除操作。 解决方法:查询时使用WITH NOLOCK。
4. 从数据库返回的记录集过大,导致程序没有响应。
原因:同上
解决方法1:尽量使用过滤条件把数据过滤后返回,如果SQL太复杂,也可使用存储过程进行处理后返回。
解决方法2:使用TOP N等方式,将结果分多次返回。
5. 使用多条SQL查询,导致效率减低。
原因:可以用一条SQL查出结果的,结果使用多条SQL,导致效率降低。
解决方法:在大部分情况下使用一条SQL就可以查出需要的结果。
注意:在多张大表(数据在几万条以上的表)的相互关联情况下,有可能一条SQL的效率反而没有多条分别查询效率高。
6. 乱用“like”,导致查询出很多相关但是无效的数据,或者导致查询速度慢。 原因:查询条件中使用“like”。
解决方法:SQL编写时尽量使用“=”。
7. 使用in,导致速度较慢。
原因:使用in的速度比较慢。
解决方法:尽量改用exist,例如:
SELECT pub_name
FROM publishers
WHERE EXISTS
FROM titles
WHERE pub_id = publishers.pub_id
AND type = 'business')
SELECT pub_name
FROM publishers
WHERE pub_id IN
(SELECT pub_id
FROM titles
WHERE type = 'business')
8. 使用UNION、MINUS或者DISTINCT导致数据库大量运算。
原因:数据库要做大量的比较工作。
解决方法:使用UNION ALL代替UNION,尽量使用过滤条件达到目的。
9. 乱用游标,导致处理数据很慢。
原因:数据量很大时使用游标会导致处理速度很慢。
解决方法:改用UPDATE,或者把数据导入临时表处理。
10. 数据库没有建索引,或者索引建的不合理(或者SQL语句没有根据索引编写),导致
数据库操作速度不快。
原因:SQL不能利用索引提交检索效率;
解决方法:数据库要针对操作的SQL建立索引并优化。
11. 使用拼接字符串,导致SQL预编译无效。
原因:写SQL语句时采用拼接字符串的方式,每次提交的SQL都不同。
解决方法:写SQL语句时尽量采用变量绑定的方式
12. 查询结果不排序,导致显示的数据杂乱无章。
原因:查询条件中没有加上排序。
解决方法:SQL编写时加上Order by??排序条件,或者通过程序后期处理。
13. 如何查看SQL的执行时间?
答:在查询分析器中执行:
SET STATISTICS TIME ON
SET STATISTICS TIME OFF
就可以查看到执行时间了,精确到毫秒,在消息里查看。
14. 如何查看SQL的执行计划?
答:在查询分析器中选择“查询”→“显示估计的执行计划”。
三亿文库包含各类专业文献、文学作品欣赏、专业论文、生活休闲娱乐、幼儿教育、小学教育、行业资料、应用写作文书、各类资格考试、外语学习资料、SQL编程中需要注意的几点43等内容。 
 实验六 T-SQL编程_计算机软件及应用_IT/计算机_专业资料。实验六 T-SQL 编程...对本次实验中要求自己完成的部分做好准备 【实验步骤】 1. 条件结构 o 在...  ‘%...%’ 进行模糊查询时,使用全文索引 14 15 16 适用于 SQL Server、MySQL 二、SQL 语句编写的注意事项 数据库系统中,索引、碎片、统计信息和锁等很多因素...  当数据第一次发布或当它重新发布时应用程序应不受影响 12 任何程序不可能使用...MAN LOGO SUN MaBell Havesonsnexttime 150 ID 1 注意:一些SQL解释器使用的...  2、实验准备。 (1)了解 T-SQL 支持的各种基本数据类型。 (2)了解自定义数据...② 写一段 T-SQL 程序调用上述函数。当向 Employees 表中插入一行记录时,首先...  SQL程序设计_计算机软件及应用_IT/计算机_专业资料。...二、要求 设计过程中,要严格遵守课程设计的时间安排...科目三实际道路驾驶考试注意事项 驾考新题抢先版 20...  编写SQL语句时常见的10种错误_计算机软件及应用_IT/计算机_专业资料。Java开发者...需要注意的是,即使 SQL 标准指定了 INTERSECTALL 和 EXCEPTALL, 但几乎没有...  T-SQL编程 5页 1下载券 T-SQL编程 25页 免费 T-SQL编程与应用 37页 免费...1 .将任意一个 3 位正整数 x=753 进行分解,然后求其各个数位上的 数字之...  需要注意几点: a) SQL 语句必须相同,包括大小写、空格、换行等; b) SQL ...涉及索引字段的 SQL 编写规则: a) 对索引字段进行 LIKE 模糊查询时, 首字母为...  12 引言 本规范用于说明在利用 PL/SQL 开发 Oracle 数据库后台应用程序时,应...(name,1,7)=’CAPITAL’ O WHERE name LIKE ‘CAPITAL%’ 4.1.2 尽量注意...筛选条件是在主查询上还是在子查询上
服务器君一共花费了207.537 ms进行了5次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议
SQL中in可以分为三类:
形如select * from t1 where f1 in ('a','b'),应该和以下两种比较效率:select * from t1 where f1='a' or f1='b' 或者 select * from t1 where f1 ='a' union all select * from t1 f1='b',你可能指的不是这一类,这里不做讨论。
形如select * from t1 where f1 in (select f1 from t2 where t2.fx='x'),其中子查询的where里的条件不受外层查询的影响,这类查询一般情况下,自动优化会转成exist语句,也就是效率和exist一样。
形如select * from t1 where f1 in (select f1 from t2 where t2.fx=t1.fx),其中子查询的where里的条件受外层查询的影响,这类查询的效率要看相关条件涉及的字段的索引情况和数据量多少,一般认为效率不如exists。除了第一类in语句都是可以转化成exists 语句的SQL,一般编程习惯应该是用exists而不用in,而很少去考虑in和exists的执行效率。
A,B两个表
当只显示一个表的数据如A,关系条件只一个如ID时,使用IN更快:select * from A where id in (select id from B)
当只显示一个表的数据如A,关系条件不只一个如ID,col1时,使用IN就不方便了,可以使用EXISTS:select * from A where exists (select 1 from B where id = A.id and col1 = A.col1)
当只显示两个表的数据时,使用IN,EXISTS都不合适,要使用连接:select * from A left join B on id = A.id
所以使用何种方式,要根据要求来定。
这是一般情况下做的测试:
set statistics io on
select * from sysobjects where exists (select 1 from syscolumns where id=syscolumns.id)
select * from sysobjects where id in (select id from syscolumns )
set statistics io off
(47 行受影响)
表'syscolpars'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 2 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
(44 行受影响)
表'syscolpars'。扫描计数 47,逻辑读取 97 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
set statistics io on
select * from syscolumns where exists (select 1 from sysobjects where id=syscolumns.id)
select * from syscolumns where id in (select id from sysobjects )
set statistics io off
(419 行受影响)
表'syscolpars'。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 15 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
(419 行受影响)
表'syscolpars'。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
测试结果(总体来讲exists比in的效率高):
效率:条件因素的索引是非常关键的
把syscolumns 作为条件:syscolumns 数据大于sysobjects
用in 扫描计数 47,逻辑读取 97 次,用exists 扫描计数 1,逻辑读取 3 次。把sysobjects作为条件:sysobjects 的数据少于 syscolumns,exists 比 in 多预读 15 次。
如果要查询每个类别的最大sid 的话
select * from test a
  where not exists(select 1 from test where sort = a.sort and sid > a.sid)
select * from test a
  where sid in (select max(sid) from test where sort = a.sort)
的执行效率要高三倍以上。
sql优化中,使用in和exist? 主要是看你的筛选条件是在主查询上还是在子查询上。
本文地址:,欢迎访问原出处。
不打个分吗?
转载随意,但请带上本文地址:
如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 。
大家都在看
阅读一百本计算机著作吧,少年
尼古拉斯·泽卡斯(Nicholas C.Zakas) (作者), 李松峰 (译者), 曹力 (译者)
《JavaScript高级程序设计(第2版)》在上一版基础上进行了大幅度更新和修订,融入了近几年来JavaScript应用发展的最新成果,几乎涵盖了所有需要理解的重要概念和最新的JavaScript应用成果。从颇具深度的JavaScript语言基础到作用域(链),从引用类型到面向对象编程,从极其灵活的匿名函数到闭包的内部机制,从浏览器对象模型(BOM)、文档对象模型(DOM)到基于事件的Web脚本设计,从XML(E4X)到Ajax及JSON,从高级前端开发技术到前沿的客户端存储,从最佳编程实践到即将成为现实的API,直至JavaScript未来的发展,全景式地展示了JavaScript高级程序设计的方方面面。
扫一扫,在手机上阅读
栏目最新博文
25,387 views
20,905 views
26,091 views
178,943 views
22,768 views
23,665 views
15,941 views
21,718 views
23,268 views
17,373 views
栏目博文推荐
9,485 views
15,004 views
7,015 views
4,976 views
7,132 views
23,268 views
12,335 views
9,458 views
30,898 views
4,591 views
任何一件事情,只要你认真去做,总是能够变得简单的。
关于网站与作者
互联网信息太多太杂,各互联网公司不断推送娱乐花边新闻,SNS,微博不断转移我们的注意力。但是,我们的时间和精力却是有限的。这里是互联网浩瀚的海洋中的一座宁静与美丽的小岛,供开发者歇息与静心潜心修炼(愿景)。
“Veda”的本义是知识、启示,希望这里能为开发者提供充足的技术资料。
我的电子邮件gonnsai(,腾讯微博:,欢迎与我联系。较大量数据的多表关联,SQL JOIN 和 IN 性能区别大吗? - 知乎4被浏览1849分享邀请回答2添加评论分享收藏感谢收起查看: 3345|回复: 21
老问题:exist一定比in效率高吗?
论坛徽章:7
还望高手指点,不甚感激!
论坛徽章:49
大部分情况都比in快!
论坛徽章:7
回复 #2 yueyangflash 的帖子
什么时候exist会比in慢呢?
招聘 : 论坛徽章:9
Tom 上面有一篇文章说明了这个问题:
the two are processed very very differently.
基本意思是 in 类似语句内部子查询驱动外部查询;exists 类似于外部查询驱动内部查询
如果使用Nested Loop的观点来看的话,驱动的数据量尽量小......
论坛徽章:1088
10g差不多了,没有这问题,从文档和某些书上可以找到端倪,关于谁是驱动表,在10g的书上已经去掉了
论坛徽章:1088
测试下,10gr2下无区别,老版本是有区别的
DINGJUN123&select * from t where t.object_name in (select t1.object_name from t1);
已选择1011行。
----------------------------------------------------------
Plan hash value:
-----------------------------------------------------------------------------
| Id&&| Operation& && && && &| Name | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-----------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& &&&|& && &|&&1270 |& &126K|& & 63& &(4)| 00:00:01 |
|*&&1 |&&HASH JOIN RIGHT SEMI|& && &|&&1270 |& &126K|& & 63& &(4)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL&&| T1& &|& &999 | 14985 |& &&&6& &(0)| 00:00:01 |
|& &3 |& &TABLE ACCESS FULL&&| T& & | 14215 |&&1207K|& & 56& &(2)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &1 - access(&T&.&OBJECT_NAME&=&T1&.&OBJECT_NAME&)
----------------------------------------------------------
& && && & 1&&recursive calls
& && && & 0&&db block gets
& && &&&269&&consistent gets
& && && & 0&&physical reads
& && && & 0&&redo size
& && &45270&&bytes sent via SQL*Net to client
& && & 1121&&bytes received via SQL*Net from client
& && && &69&&SQL*Net roundtrips to/from client
& && && & 0&&sorts (memory)
& && && & 0&&sorts (disk)
& && & 1011&&rows processed
DINGJUN123&select * from t where exists (select 1 from t1 where t.object_name=t1.object_name);
已选择1011行。
----------------------------------------------------------
Plan hash value:
-----------------------------------------------------------------------------
| Id&&| Operation& && && && &| Name | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-----------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& &&&|& && &|&&1270 |& &126K|& & 63& &(4)| 00:00:01 |
|*&&1 |&&HASH JOIN RIGHT SEMI|& && &|&&1270 |& &126K|& & 63& &(4)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL&&| T1& &|& &999 | 14985 |& &&&6& &(0)| 00:00:01 |
|& &3 |& &TABLE ACCESS FULL&&| T& & | 14215 |&&1207K|& & 56& &(2)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &1 - access(&T&.&OBJECT_NAME&=&T1&.&OBJECT_NAME&)
----------------------------------------------------------
& && && & 1&&recursive calls
& && && & 0&&db block gets
& && &&&269&&consistent gets
& && && & 0&&physical reads
& && && & 0&&redo size
& && &45270&&bytes sent via SQL*Net to client
& && & 1121&&bytes received via SQL*Net from client
& && && &69&&SQL*Net roundtrips to/from client
& && && & 0&&sorts (memory)
& && && & 0&&sorts (disk)
& && & 1011&&rows processed
DINGJUN123&select * from t1 where t1.object_name in (select t.object_name from t);
已选择999行。
----------------------------------------------------------
Plan hash value:
---------------------------------------------------------------------------
| Id&&| Operation& && && & | Name | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
---------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& &|& && &|& &999 | 96903 |& & 62& &(2)| 00:00:01 |
|*&&1 |&&HASH JOIN SEMI& & |& && &|& &999 | 96903 |& & 62& &(2)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL| T1& &|& &999 | 78921 |& &&&6& &(0)| 00:00:01 |
|& &3 |& &TABLE ACCESS FULL| T& & | 14215 |& &249K|& & 56& &(2)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &1 - access(&T1&.&OBJECT_NAME&=&T&.&OBJECT_NAME&)
----------------------------------------------------------
& && && & 1&&recursive calls
& && && & 0&&db block gets
& && && &96&&consistent gets
& && && & 0&&physical reads
& && && & 0&&redo size
& && &44717&&bytes sent via SQL*Net to client
& && & 1110&&bytes received via SQL*Net from client
& && && &68&&SQL*Net roundtrips to/from client
& && && & 0&&sorts (memory)
& && && & 0&&sorts (disk)
& && &&&999&&rows processed
DINGJUN123&select * from t1 where exists (select 1 from t where t.object_name=t1.object_name);
已选择999行。
----------------------------------------------------------
Plan hash value:
---------------------------------------------------------------------------
| Id&&| Operation& && && & | Name | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
---------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& &|& && &|& &999 | 96903 |& & 62& &(2)| 00:00:01 |
|*&&1 |&&HASH JOIN SEMI& & |& && &|& &999 | 96903 |& & 62& &(2)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL| T1& &|& &999 | 78921 |& &&&6& &(0)| 00:00:01 |
|& &3 |& &TABLE ACCESS FULL| T& & | 14215 |& &249K|& & 56& &(2)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &1 - access(&T&.&OBJECT_NAME&=&T1&.&OBJECT_NAME&)
----------------------------------------------------------
& && && & 1&&recursive calls
& && && & 0&&db block gets
& && && &96&&consistent gets
& && && & 0&&physical reads
& && && & 0&&redo size
& && &44717&&bytes sent via SQL*Net to client
& && & 1110&&bytes received via SQL*Net from client
& && && &68&&SQL*Net roundtrips to/from client
& && && & 0&&sorts (memory)
& && && & 0&&sorts (disk)
& && &&&999&&rows processed
招聘 : 论坛徽章:9
回复 #6 dingjun123 的帖子
论坛徽章:7
回复 #6 dingjun123 的帖子
多谢老兄了!
论坛徽章:9
关于这个东西其实需要考虑一个问题,为什么以前会有这样的说法。
其实就是因为ORACLE CBO或者RBO的缺陷造成的,有些计划可能IN走不出来,但是EXISTS走的出来,还存在相反的情况。
随着优化器的升级,ORACLE能够考虑到这些问题。就好比我们说IN通常走NESTED LOOP,而exists倾向HASH, 但是事实上IN也可以走HASH. 这就不存在谁好谁坏的问题。计划能走到一样,自然就没所谓的性能区别。
举一个例子,update a set a.xx=(select xx from b where a.xx=b.xx ) where exists (select 1 from a,b where a.xx=b.xx)和
update (select a.xx,b.xx from a,b where a.xx=b.xx) set a.xx=b.xx
这2条SQL从目前来看,在更新数据量多的情况,下面SQL会比上面好很多。 而且上面的SQL一看就好像走NESTED LOOP,但是是否一定是NESTED LOOP呢? 难道上面SQL走不出HASH?
我自己测试感觉即使加了HINT,上面SQL也走不出HASH。 但是我相信这是优化器的问题。 以后一定会出现上面和下面SQL一样快的版本。
论坛徽章:9
其实说来说去还是一个问题,CBO到底多聪明。 能不能走出应该走的计划。
itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有    
 北京市公安局海淀分局网监中心备案编号:10 广播电视节目制作经营许可证:编号(京)字第1149号}

我要回帖

更多关于 sqlserver exist 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信