经常有人问到
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'