現象 下麵的語句, 能查到deviceid 為DEV005M0的記錄, 但是加上deviceid = 'DEV005M0'這個條件後, 查詢語句查不出結果了。 語句如下: 當註釋掉deviceid = 'DEV005M0', 查詢結果如下: 當增加deviceid = 'DEV005M0',查詢結果 ...
現象
下麵的語句, 能查到deviceid 為DEV005M0的記錄, 但是加上deviceid = 'DEV005M0'這個條件後, 查詢語句查不出結果了。
語句如下:
select * from
( select deviceid deviceid, port, cvlan, status, funcswitch,
decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
decode(funcswitch, 3, pvlan, 1,
lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
from vlanstatus_pre2bak
)
where funcswitch <> 2 and evlan is null -- and deviceid = 'DEV005M0';
當註釋掉deviceid = 'DEV005M0', 查詢結果如下:
當增加deviceid = 'DEV005M0',查詢結果沒有記錄:
deviceid的數據類型為char(8), vlanstatus_pre2bak的deviceid數據也沒有空格等特殊字元, 非常詭異。下麵來具體分析。
分析如下
1. 查詢語句, 查詢沒有記錄
select * from
( select deviceid deviceid, port, cvlan, status, funcswitch,
decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
decode(funcswitch, 3, pvlan, 1,
lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
from vlanstatus_pre2bak
)
where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0' ;
或者:
with tmptab as
(
select deviceid deviceid, port, cvlan, status, funcswitch,
decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
decode(funcswitch, 3, pvlan, 1,
lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
from vlanstatus_pre2bak
)
select * from tmptab
where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0' ;
查看執行計劃:
SQL> set lines 200
SQL> set pages 200
SQL> explain plan for
2 select * from
3 ( select deviceid deviceid, port, cvlan, status, funcswitch,
4 decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
5 decode(funcswitch, 3, pvlan, 1,
6 lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
7 from vlanstatus_pre2bak
8 )
9 where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0' ;
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2175325539
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 70 | 49350 | 692 (1)| 00:00:09 |
|* 1 | VIEW | | 70 | 49350 | 692 (1)| 00:00:09 |
| 2 | WINDOW SORT | | 70 | 3430 | 692 (1)| 00:00:09 |
|* 3 | TABLE ACCESS FULL| VLANSTATUS_PRE2BAK | 70 | 3430 | 691 (1)| 00:00:09 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL)
3 - filter("DEVICEID"='DEV005M0')
已選擇16行。
SQL>
查看ID為3的謂詞過濾(3 - filter("DEVICEID"='DEV005M0')), 說明先在表VLANSTATUS_PRE2BAK執行了deviceid = 'DEV005M0'操作。ID為1的謂詞過濾只有兩個(1 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL)),說明這個查詢語句先在子查詢裡面過濾了deviceid = 'DEV005M0'的記錄,然後在整個查詢視圖執行過濾條件FUNCSWITCH<>2 AND EVLAN IS NULL。這個現象就是謂詞推入。
2. 使用materialize的hint避免謂詞推入
with tmptab as
(
select /*+materialize*/ deviceid deviceid, port, cvlan, status, funcswitch,
decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
decode(funcswitch, 3, pvlan, 1,
lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
from vlanstatus_pre2bak
)
select * from tmptab
where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0' ;
SQL> set lines 200
SQL> set pages 200
SQL> explain plan for
2 with tmptab as
3 (
4 select /*+materialize*/ deviceid deviceid, port, cvlan, status, funcswitch,
5 decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
6 decode(funcswitch, 3, pvlan, 1,
7 lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
8 from vlanstatus_pre2bak
9 )
10 select * from tmptab
11 where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0' ;
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1444871666
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 313K| 210M| | 5062 (1)| 00:01:01 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D66CE_DF9DBBFB | | | | | |
| 3 | WINDOW SORT | | 313K| 14M| 20M| 4492 (1)| 00:00:54 |
| 4 | TABLE ACCESS FULL | VLANSTATUS_PRE2BAK | 313K| 14M| | 690 (1)| 00:00:09 |
|* 5 | VIEW | | 313K| 210M| | 570 (1)| 00:00:07 |
| 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D66CE_DF9DBBFB | 313K| 14M| | 570 (1)| 00:0
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL AND "DEVICEID"='DEV005M0')
已選擇18行。
SQL>
查看ID為5的謂詞過濾條件, 三個條件都是發生在視圖view上面。
3. 使用trim或者拼接一個空的字元
select * from
( select trim(deviceid) deviceid, port, cvlan, status, funcswitch,
decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
decode(funcswitch, 3, pvlan, 1,
lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
from vlanstatus_pre2bak
)
where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0' ;
查看執行計劃:
SQL> set lines 200
SQL> set lines 300
SQL> set pages 200
SQL> explain plan for
2 select * from
3 ( select trim(deviceid) deviceid, port, cvlan, status, funcswitch,
4 decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
5 decode(funcswitch, 3, pvlan, 1,
6 lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
7 from vlanstatus_pre2bak
8 )
9 where funcswitch <> 2 and evlan is null and deviceid = 'DEV005M0';
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2175325539
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 313K| 209M| | 4492 (1)| 00:00:54 |
|* 1 | VIEW | | 313K| 209M| | 4492 (1)| 00:00:54 |
| 2 | WINDOW SORT | | 313K| 14M| 20M| 4492 (1)| 00:00:54 |
| 3 | TABLE ACCESS FULL| VLANSTATUS_PRE2BAK | 313K| 14M| | 690 (1)| 00:00:09 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL AND "DEVICEID"='DEV005M0')
已選擇15行。
SQL>
查看謂詞過濾, 三個過濾條件都發生在ID為1的view上面。
小海蟹出品