您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Oracle中where條件執(zhí)行順序是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識(shí)有一定的了解。
問題:
SYS@proc> create table t as select * from v$parameter;
Table created.
SYS@proc> select value from t where name='db_block_size' and to_number(value)=8192;
VALUE
--------------------------------------------------------------------------------
8192
SYS@proc> select value from v$parameter where name='db_block_size' and to_number(value)=8192;
select value from v$parameter where name='db_block_size' and to_number(value)=8192
*
ERROR at line 1:
ORA-01722: invalid number
為什么語句“select value from t where name='db_block_size' and to_number(value)=8192;”執(zhí)行成功,換成v$parameter卻報(bào)錯(cuò)。
實(shí)驗(yàn)研究過程:
SYS@proc> set autotrace on
SYS@proc> analyze table t compute statistics;
Table analyzed.
SYS@proc> select value from t where name='db_block_size' and to_number(value)=8192;
VALUE
--------------------------------------------------------------------------------
8192
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 4 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 26 | 4 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("NAME"='db_block_size' AND TO_NUMBER("VALUE")=8192)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
9 consistent gets
0 physical reads
0 redo size
525 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
一開始看到這個(gè)執(zhí)行計(jì)劃很懵逼,完全搞不懂為什么能夠執(zhí)行成功,做10046,10053,改寫sql加hint還是搞不懂。
最后猜想Oracle在filter("NAME"='db_block_size' AND TO_NUMBER("VALUE")=8192)這個(gè)步驟,是先對數(shù)據(jù)做name='db_block_size'的過濾,在做to_number('value')=8192的過濾。
若是能將謂詞信息改變成filter(TO_NUMBER("VALUE") AND "NAME"='db_block_size'=8192)并且執(zhí)行報(bào)錯(cuò),那么猜想就是正確的。
嘗試將sql語句的and條件調(diào)換位置"select value from t whereto_number(value)=8192 and name='db_block_size';",不過還是和原來一樣,這里省略步驟。
這里構(gòu)造其他測試表:
SYS@proc> create table a(id1 int,id2 int,id3 int,id4 int);
Table created.
SYS@proc> insert into a values(1,1,1,0);
1 row created.
SYS@proc> commit;
Commit complete.
SYS@proc> select * from a;
ID1 ID2 ID3 ID4
---------- ---------- ---------- ----------
1 1 1 0
這里執(zhí)行以下4條sql語句:
①Select 'ok' From aaa where id1/id2=1 and id3/id4=2;
②Select 'ok' From aaa where id1/id2=2 and id3/id4=2;
③Select 'ok' From aaa where id3/id4=2 and id1/id2=1;
④Select 'ok' From aaa where id3/id4=2 and id1/id2=2;
其中①和③,②和④只是where后條件位置互換而已。
查看執(zhí)行結(jié)果:
SYS@proc> Select 'ok' From aaa where id1/id2=1 and id3/id4=2;
Select 'ok' From aaa where id1/id2=1 and id3/id4=2
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
SYS@proc> Select 'ok' From aaa where id1/id2=2 and id3/id4=2;
no rows selected
SYS@proc> Select 'ok' From aaa where id3/id4=2 and id1/id2=1;
Select 'ok' From aaa where id3/id4=2 and id1/id2=1
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
SYS@proc> Select 'ok' From aaa where id3/id4=2 and id1/id2=2;
Select 'ok' From aaa where id3/id4=2 and id1/id2=2
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
②和④只是位置不同,但是一個(gè)卻正常執(zhí)行,一個(gè)卻報(bào)錯(cuò)了。
這里查看兩條sql的執(zhí)行計(jì)劃:
SYS@proc> explain plan for Select 'ok' From aaa where id1/id2=2 and id3/id4=2;
Explained.
SYS@proc> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 864433273
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| AAA | 1 | 12 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("ID1"/"ID2"=2 AND "ID3"/"ID4"=2)
13 rows selected.
SYS@proc> explain plan for Select 'ok' From aaa where id3/id4=2 and id1/id2=2;
Explained.
SYS@proc> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 864433273
------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| AAA | 1 | 12 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("ID3"/"ID4"=2 AND "ID1"/"ID2"=2)
13 rows selected.
這里對比謂詞信息剛好是兩個(gè)位置不同,導(dǎo)致執(zhí)行結(jié)果不一樣。
正好說明上邊的問題的猜想:
最后猜想Oracle在filter("NAME"='db_block_size' AND TO_NUMBER("VALUE")=8192)這個(gè)步驟,是先對數(shù)據(jù)做name='db_block_size'的過濾,在做to_number('value')=8192的過濾。
若是能將謂詞信息改變成filter(TO_NUMBER("VALUE") AND "NAME"='db_block_size'=8192)并且執(zhí)行報(bào)錯(cuò),那么猜想就是正確的。
由此問題解決。
其他:
SYS@proc> create table test (id int);
Table created.
SYS@proc> insert into test values(null);
1 row created.
SYS@proc> commit;
Commit complete.
SYS@proc> select * from test;
ID
----------
SYS@proc> set autotrace on
SYS@proc> select value from t,test a where a.id||name='db_block_size' and to_number(a.id||t.value)=8192;
VALUE
--------------------------------------------------------------------------------
8192
Execution Plan
----------------------------------------------------------
Plan hash value: 423998170
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 39 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| TEST | 1 | 13 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| T | 1 | 26 | 4 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(TO_CHAR("A"."ID")||"NAME"='db_block_size' AND
TO_NUMBER(TO_CHAR("A"."ID")||"T"."VALUE")=8192)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
32 recursive calls
0 db block gets
28 consistent gets
0 physical reads
0 redo size
525 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
1 rows processed
SYS@proc> set autotrace off
SYS@proc> select value from t,test a where to_number(a.id||t.value)=8192 and a.id||name='db_block_size';
select value from t,test a where to_number(a.id||t.value)=8192 and a.id||name='db_block_size'
*
ERROR at line 1:
ORA-01722: invalid number
SYS@proc> explain plan for select value from t,test a where to_number(a.id||t.value)=8192 and a.id||name='db_block_size';
Explained.
SYS@proc> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 423998170
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 39 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| TEST | 1 | 13 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| T | 1 | 26 | 4 (0)| 00:00:01 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(TO_NUMBER(TO_CHAR("A"."ID")||"T"."VALUE")=8192 AND
TO_CHAR("A"."ID")||"NAME"='db_block_size')
16 rows selected.
所以where后邊條件的執(zhí)行順序,實(shí)際上和執(zhí)行計(jì)劃謂詞信息的順序有關(guān),和where的位置無關(guān)。
網(wǎng)上有些在10g做實(shí)驗(yàn)得出結(jié)論是從右到左,在11g里邊,按照相同步驟執(zhí)行并得不出相同結(jié)論。
問題延伸:
filter("NAME"='db_block_size' AND TO_NUMBER("VALUE")=8192),這里是一次性掃描出全部數(shù)據(jù)在進(jìn)行過濾,還是一行一行獲取在判斷的。
延伸鏈接:http://blog.itpub.net/30174570/viewspace-2149212/
關(guān)于Oracle中where條件執(zhí)行順序是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。