相关文章推荐
鬼畜的雪糕  ·  请教Java ...·  2 年前    · 
温暖的煎饼  ·  npm 安装python-掘金·  2 年前    · 
读研的木耳  ·  在 Docker 中使用 ...·  2 年前    · 
经常有人问到 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优化器模式下,表应按结果记录数从大到小的顺序从左到右来排列,因为表间连接时,最右边的表会被放到嵌套循环的最外层。最外层的循环次数越少,效率越高。

学生表 Studentid(编号)name(名字)age(年龄)height(身高)1Tommy261702Jerry231803Frank30160如表所示,这里只是呈现了3条数据,我们这里假设有1万条数据,查询年龄25岁以上,身高170以上的全部学生Select * from Student whereage > 25andheight > 170;//正常情况下可以这么写,... 整天说 SQL 优化 SQL 优化 ,到底怎么才算是 SQL 优化 呢,下面从百度总结了一些关于 Oracle 里常用的一些有效的 优化 方法。仅供参考,文章内容来源于网络。 35条 优化 规则 (1)优先考虑建立索引 对查询进行 优化 ,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 (2)需要当心的WHERE子句 【IT168技术文档】经常有人问到 oracle 中的Where子句的 条件 书写 顺序 是否对 SQL 性能 影响 ,我的直觉是没有 影响 ,因为如果这个 顺序 影响 Oracle 应该早就能够做到自动 优化 ,但一直没有关于这方面的确凿证据。在网上查到的... 1、慎重使用count(distinct col) distinct会将col列所有数据保存在内存中,形成一个类似hash的结构,速度很快;但是在大数据背景下,因为col列所有值都会形成以key值,极有可能发生OOM(内存用完) 解决方案: 可以考虑使用Group By 或者 ROW_NUMBER() OVER(PARTITION BY col)方式代替COUNT(DISTINCT col) 原帖地址:http://blog.sina.com.cn/s/blog_4586764e0100mdif.html 经常有人问到 oracle 中的Where子句的 条件 书写 顺序 是否对 SQL 性能 影响 ,我的直觉是没有 影响 ,因为如果这个 顺序 影响 Oracle 应该早就能够做到自动 优化 ,但一直没有关于这方面的确凿证据。在网上查到的文章,一般认为在RBO 优化 器模式下无 影响 (10G开始,... 经常有人问到 oracle 中的Where子句的 条件 书写 顺序 是否对 SQL 性能 影响 ,我的直觉是没有 影响 ,因为如果这个 顺序 影响 Oracle 应该早就能够做到自动 优化 ,但一直没有关于这方面的确凿证据。在网上查到的文章,一般认为在RBO 优化 器模式下无 影响 (10G开始,缺省为RBO 优化 器模式),而在CBO 优化 器模式下有 影响 ,主要有两种观点: a.能使结果最少的 条件 放在最右边, SQL 执行是按从右到左进行结... -- Start 在 WHERE 子句中应该尽量避免在列上使用函数,因为这样做会使该列上的索引失效, 影响 SQL 语句的 性能 。即使该列上没有索引,也应该避免在列上使用函数。考虑下面的情况: CREATE TABLE EMPLOYEE NAME VARCHAR2(20) NOT NULL,---姓名 REGISTERDATE TIMESTAMP---注册时间 近期做了一个存储过程,执行时发现非常的慢,竟然需要6、7秒! 经排查,发现时间主要都耗在了其中一段查询语句上。这个语句用于查出结构相同的两个表中,其中两个字段的任一个字段数据相同的记录。 例如,A表的结构如下所示: --会员表 CREATE Table Member MemberID int, --会员ID MemberName ... 在编写 SQL 时,会建议将选择性高(过滤数据多)的 条件 放到WHERE 条件 的前面,这是为了让查询 优化 器优先考虑这些 条件 ,减少生成最优(或相对最优)的执行计划的时间,但最终的执行计划生成过滤 顺序 还是决定这些 条件 的选择性与判断bool值的容易程度 测试代码: SELECT * INTO #T1 FROM sys.all_columns SELECT * INTO #T2 FROM sys.... 最近在后台导出数据到Excel,考虑到可能数据量大使用了c扩展xlswriter来做Excel处理,首先在本地测试,1w条数据花费了40s,不太理想。 thinkphp 版本为 5.0.4 于是想知道在哪一步花费的时间比较多,打断点日志发现,导出过程只花了1秒,处理数据也只花了2s,但是有一个查询却花了36s,然后日志文件记录的该 sql 执行时间只有零点几秒,于是将这个 sql 拿到navicate执行,发现也只需要0.3s,好吧,找到原因了,应该是在组装 sql 的时候耗时较长。我的查询是这样的: $users = SQL Server——查询 条件 顺序 对查询 性能 影响 经常能看到或听到关于查询 条件 顺序 对查询 性能 影响 ,下面给出了测试,相信看完测试结果,就能获得自己的判断。 where productId=1 and tradedate>'2018-05-01'