惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - 知道得越多知道的越少

window10上登录Oracle时提示ORA-12546:Permission denied 大表的主键创建优化技术(转一篇有深度的文章) Oracle并行执行特性应用初探 解决Rhel5上安装VMWare tools的问题 Oracle 性能诊断艺术 第四章 笔记 Oracle国外站点汇集 在客户端通过外部表访问Trace文件的内容 查出全表扫描的相关SQL语句 用SQL语句求排除断号的号码串 易用性规范 64位Oracle数据库环境下安装使用32位的PLSQL-Developer 使用Pivot进行行列转换不能合并为一行的问题 删除Oracle程序,重装后遇到的两个小问题 闪回查询,9i,10G到11G的不断增强 归档日志充满的问题解决 ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务 问题解决 生成SQL记录集的一些数据 导入的数据,删除约束后没有自动删除对应索引,重建约束出错 如何取出某一用户的密码,再原封不动的改回去?
SQL条件的顺序对性能的影响
知道得越多知道的越少 · 2009-09-25 · via 博客园 - 知道得越多知道的越少

       经常有人问到oracle中的Where子句的条件书写顺序是否对SQL性能有影响,我的直觉是没有影响,因为如果这个顺序有影响,Oracle应该早就能够做到自动优化,但一直没有关于这方面的确凿证据。在网上查到的文章,一般认为在RBO优化器模式下无影响(10G开始,缺省为RBO优化器模式),而在CBO优化器模式下有影响,主要有两种观点:

a.能使结果最少的条件放在最右边,SQL执行是按从右到左进行结果集的筛选的;

b.有人试验表明,能使结果最少的条件放在最左边,SQL性能更高。

       查过oracle8到11G的在线文档,关于SQL优化相关章节,没有任何文档说过where子句中的条件对SQL性能有影响,到底哪种观点是对的,没有一种确切的结论,只好自己来做实验证明。结果表明,SQL条件的执行是从右到左的,但条件的顺序对SQL性能没有影响

实验一:证明了SQL的语法分析是从右到左的

       下面的试验在9i和10G都可以得到相同的结果: 第1条语句执行不会出错,第2条语句会提示除数不能为零。

1.Select 'ok' From Dual Where 1 / 0 = 1 And 1 = 2;

2.Select 'ok' From Dual Where 1 = 2 And 1 / 0 = 1;

证明了SQL的语法分析是从右到左的。

实验二:证明了SQL条件的执行是从右到左的

drop table temp;

create table temp( t1 varchar2(10),t2 varchar2(10)); 

insert into temp values('zm','abcde');

insert into temp values('sz','1');

insert into temp values('sz','2');

commit;

1. select * from temp where to_number(t2)>1 and t1='sz';

2. select * from temp where t1='sz' and to_number(t2)>1;

9i上执行, 第1条语句执行不会出错,第2条语句会提示“无效的数字”

10G上执行,两条语句都不会出错。

说明:9i上,SQL条件的执行确实是从右到左的,但是10G做了什么调整呢?

实验三:证明了在10g上SQL条件的执行是从右到左的

Create Or Replace Function F1(v_In Varchar2) Return Varchar2 Is

Begin

 Dbms_Output.Put_Line('exec F1');

 Return v_In;

End F1;

/

Create Or Replace Function F2(v_In Varchar2) Return Varchar2 Is

Begin

 Dbms_Output.Put_Line('exec F2');

 Return v_In;

End F2;

/

SQL> set serverout on;

SQL> select 1 from dual where f1('1')='1' and f2('1')='1';

         1

----------

         1

exec F2

exec F1

SQL> select 1 from dual where f2('1')='1' and f1('1')='1';

         1

----------

         1

exec F1

exec F2

结果表明,SQL条件的执行顺序是从右到左的。

       那么,根据这个结果来分析,把能使结果最少的条件放在最右边,是否会减少其它条件执行时所用的记录数量,从而提高性能呢?

例如:下面的SQL条件,是否应该调整SQL条件的顺序呢?

Where A.结帐id Is Not Null

And A.记录状态<>0

And A.记帐费用=1

And (Nvl(A.实收金额, 0)<>Nvl(A.结帐金额, 0) Or Nvl(A.结帐金额, 0)=0)

And A.病人ID=[1] And Instr([2],','||Nvl(A.主页ID,0)||',')>0

And A.登记时间Between [3] And [4]

And A.门诊标志<>1

       实际上,从这条SQL语句的执行计划来分析,Oracle首先会找出条件中使用索引或表间连接的条件,以此来过滤数据集,然后对这些结果数据块所涉及的记录逐一检查是否符合所有条件,所以条件顺序对性能几乎没有影响。

       如果没有索引和表间连接的情况,条件的顺序是否对性能有影响呢?再来看一个实验。

实验四:证明了条件的顺序对性能没有影响。

SQL> select count(*) from 诊疗项目目录 where 操作类型='1';

 COUNT(*)

----------

      3251

SQL> select count(*) from 诊疗项目目录 where 类别='Z';

 COUNT(*)

----------

       170

SQL> select count(*) from 诊疗项目目录 where 类别='Z' and 操作类型='1';

 COUNT(*)

----------

         1

Declare

 V1 Varchar2(20);

Begin

 For I In 1 .. 1000 Loop   

   --Select 名称 Into V1 From 诊疗项目目录 Where 类别 = 'Z' And 操作类型 = '1';

   select 名称 Into V1 from 诊疗项目目录 where 操作类型='1' and 类别='Z';

 End Loop;

End;

/

上面的SQL按两种方式分别执行了1000次查询,结果如下:

操作类型 = '1'在最右       |      类别='Z'在最右

0.093                            |      1.014

1.06                              |      0.999

0.998                            |      1.014

       按理说,从右到左的顺序执行,“类别='Z'”在最右边时,先过滤得到170条记录,再从中找符合“操作类型 = '1'”的,比较而言,“操作类型 = '1'”在最右边时,先过滤得到3251条记录,再从中找符合“类别='Z'”,效率应该要低些,而实际结果却是两者所共的时间差不多。

       其实,从Oracle的数据访问原理来分析,两种顺序的写法,执行计划都是一样的,都是全表扫描,都要依次访问该表的所有数据块,对每一个数据块中的行,逐一检查是否同时符合两个条件。所以,就不存在先过滤出多少条数据的问题。

       综上所述,Where子句中条件的顺序对性能没有影响(不管是CBO还是RBO优化器模式),注意,额外说一下,这里只是说条件的顺序,不包含表的顺序。在RBO优化器模式下,表应按结果记录数从大到小的顺序从左到右来排列,因为表间连接时,最右边的表会被放到嵌套循环的最外层。最外层的循环次数越少,效率越高。