中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解SQL優化中連接謂詞推入

發布時間:2021-11-29 15:55:19 來源:億速云 閱讀:121 作者:柒染 欄目:關系型數據庫

這篇文章將為大家詳細講解有關如何理解SQL優化中連接謂詞推入,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

SQL優化之連接謂詞推入:

環境準備:
create table emp1 as select * from emp;
create table emp2 as select * from emp;
create index idx_emp1 on emp1(empno);
create index idx_emp2 on emp2(empno);
create or replace  view  emp_view as select emp1.empno as empno1 from emp1;
create or replace view emp_view_union as select emp1.empno as empno1 from emp1 union all select emp2.empno as empno1 from emp2;


賦權,scott用戶可以開啟set autot
grant select on v_$sesstat to scott;
grant select on v_$statname to scott;
grant select on v_$mystat to scott;


sql范例1:
select /*+ no_merge(emp_view) */emp.empno from emp,emp_view where emp.empno=emp_view.empno1(+) and emp.ename='FROD';
可以看到emp表和emp_view視圖左外連接,視圖是補充表。


查看執行計劃:
SQL> set autot traceonly
SQL> set line 250
SQL> select /*+ no_merge(emp_view) */emp.empno from emp,emp_view where emp.empno=emp_view.empno1(+) and emp.ename='FROD';


no rows selected




Execution Plan
----------------------------------------------------------
Plan hash value: 101695337


------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          |     1 |    12 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS OUTER     |          |     1 |    12 |     4   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL     | EMP      |     1 |    10 |     3   (0)| 00:00:01 |
|   3 |   VIEW PUSHED PREDICATE | EMP_VIEW |     1 |     2 |     1   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN     | IDX_EMP1 |     1 |    13 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - filter("EMP"."ENAME"='FROD')
   4 - access("EMP1"."EMPNO"="EMP"."EMPNO")


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          7  consistent gets
          0  physical reads
          0  redo size
        333  bytes sent via SQL*Net to client
        508  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed


該執行計劃比較好理解:步驟2與步驟3同級,但是步驟2沒有子ID,所以最先執行步驟2.
步驟2:該步驟有一個filter條件filter("EMP"."ENAME"='FROD'),全表掃描emp表,找出ename=frod的所有數據
步驟4:索引范圍掃描,目標條件滿足access("EMP1"."EMPNO"="EMP"."EMPNO"),這里把視圖和表左外連接的條件推入到了視圖中。
步驟3:VIEW PUSHED PREDICATE說明沒有做視圖合并,把視圖當做一個獨立單元來執行,但是把外部條件推入到了視圖內部
。如果沒有做這次連接謂詞推入,那么就不會在抓取視圖內部數據的時候用到emp1表上的索引,那樣的話就會全表掃描了。
步驟1:然后兩個結果集做循環嵌套外連接,得到結果。


下面驗證一下,連接謂詞未推入,抓取視圖數據集的時候不會走emp1的索引,而是全表掃描emp1了。
select /*+ no_merge(emp_view) no_push_pred(emp_view) */emp.empno from emp,emp_view where emp.empno=emp_view.empno1(+) and emp.ename='FROD';


Execution Plan
----------------------------------------------------------
Plan hash value: 3053348535


-----------------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |          |     1 |    23 |     6  (17)| 00:00:01 |
|   1 |  MERGE JOIN OUTER            |          |     1 |    23 |     6  (17)| 00:00:01 |
|*  2 |   TABLE ACCESS BY INDEX ROWID| EMP      |     1 |    10 |     2   (0)| 00:00:01 |
|   3 |    INDEX FULL SCAN           | PK_EMP   |    14 |       |     1   (0)| 00:00:01 |
|*  4 |   SORT JOIN                  |          |    14 |   182 |     4  (25)| 00:00:01 |
|   5 |    VIEW                      | EMP_VIEW |    14 |   182 |     3   (0)| 00:00:01 |
|   6 |     TABLE ACCESS FULL        | EMP1     |    14 |   182 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - filter("EMP"."ENAME"='FROD')
   4 - access("EMP"."EMPNO"="EMP_VIEW"."EMPNO1"(+))
       filter("EMP"."EMPNO"="EMP_VIEW"."EMPNO1"(+))


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         11  recursive calls
          0  db block gets
          9  consistent gets
          1  physical reads
          0  redo size
        333  bytes sent via SQL*Net to client
        508  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed


這時可以看到對emp表進行索引全掃描,利用條件"EMP"."ENAME"='FROD'回表,得到數據集;視圖并沒有走emp1的索引,而是全表掃描,并將結果進行排序,然后與第一個結果集進行排序合并外連接。


范例sql:
select emp.empno from emp,emp_view_union where emp.empno=emp_view_union.empno1 and emp.ename='FROD';
Execution Plan
----------------------------------------------------------
Plan hash value: 2223410919


-------------------------------------------------------------------------------------
| Id  | Operation                     | Name           | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                |     2 |    24 |     5   (0)|
|   1 |  NESTED LOOPS                 |                |     2 |    24 |     5   (0)|
|*  2 |   TABLE ACCESS FULL           | EMP            |     1 |    10 |     3   (0)|
|   3 |   VIEW                        | EMP_VIEW_UNION |     1 |     2 |     2   (0)|
|   4 |    UNION ALL PUSHED PREDICATE |                |       |       |            |
|*  5 |     INDEX RANGE SCAN          | IDX_EMP1       |     1 |    13 |     1   (0)|
|*  6 |     INDEX RANGE SCAN          | IDX_EMP2       |     1 |    13 |     1   (0)|
-------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - filter("EMP"."ENAME"='FROD')
   5 - access("EMP1"."EMPNO"="EMP"."EMPNO")
   6 - access("EMP2"."EMPNO"="EMP"."EMPNO")


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         28  recursive calls
          0  db block gets
         39  consistent gets
          0  physical reads
          0  redo size
        333  bytes sent via SQL*Net to client
        508  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed
因為視圖定義中有union all,所以EMP_VIEW_UNION不能做視圖合并,但是可以做連接謂詞推入,所以看到步驟5和步驟6將連接條件推入到了視圖內部,從而走了emp1和emp2表的索引。然后將結果集與全表掃描emp表得到的ename=frod的結果集做循環嵌套連接,得到最終結果。
同樣地,如果阻止了連接謂詞推入,那么視圖內部結果集會按照全表掃描。


select /*+ no_push_pred(emp_view_union)*/emp.empno from emp,emp_view_union where emp.empno=emp_view_union.empno1 and emp.ename='FROD';


Execution Plan
----------------------------------------------------------
Plan hash value: 894575737
------------------------------------------------------------------------------------
| Id  | Operation                    | Name           | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                |     2 |    46 |     9  (12)|
|   1 |  MERGE JOIN                  |                |     2 |    46 |     9  (12)|
|*  2 |   TABLE ACCESS BY INDEX ROWID| EMP            |     1 |    10 |     2   (0)|
|   3 |    INDEX FULL SCAN           | PK_EMP         |    14 |       |     1   (0)|
|*  4 |   SORT JOIN                  |                |    28 |   364 |     7  (15)|
|   5 |    VIEW                      | EMP_VIEW_UNION |    28 |   364 |     6   (0)|
|   6 |     UNION-ALL                |                |       |       |            |
|   7 |      TABLE ACCESS FULL       | EMP1           |    14 |   182 |     3   (0)|
|   8 |      TABLE ACCESS FULL       | EMP2           |    14 |   182 |     3   (0)|
------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - filter("EMP"."ENAME"='FROD')
   4 - access("EMP"."EMPNO"="EMP_VIEW_UNION"."EMPNO1")
       filter("EMP"."EMPNO"="EMP_VIEW_UNION"."EMPNO1")


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         14  recursive calls
          0  db block gets
         14  consistent gets
          0  physical reads
          0  redo size
        333  bytes sent via SQL*Net to client
        508  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed
注意:能否做謂詞推入,與視圖能否合并,是否是內嵌視圖沒有關系,與目標視圖的類型,與外部查詢之間的連接類型以及連接方法有關。
如下是一個無法謂詞推入的sql:
原因:視圖在外鏈接的右側。
select /*+ no_merge(emp_view) use_nl(emp_view) push_pred(emp_view) */emp.empno from emp,emp_view where emp.empno=emp_view.empno1 and ename='FROD';


Execution Plan
----------------------------------------------------------
Plan hash value: 3774177413


--------------------------------------------------------------------------------
| Id  | Operation           | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |          |     1 |    23 |     6   (0)| 00:00:01 |
|   1 |  NESTED LOOPS       |          |     1 |    23 |     6   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL | EMP      |     1 |    10 |     3   (0)| 00:00:01 |
|*  3 |   VIEW              | EMP_VIEW |     1 |    13 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| EMP1     |    14 |   182 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - filter("ENAME"='FROD')
   3 - filter("EMP"."EMPNO"="EMP_VIEW"."EMPNO1")


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         11  recursive calls
          0  db block gets
         14  consistent gets
          0  physical reads
          0  redo size
        333  bytes sent via SQL*Net to client
        508  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed


連接謂詞推入條件:
視圖定義語句中存在union all/union/group by/distinct
視圖與外部查詢之間是外連接,半連接,反連接
以上只要滿足一種條件就可以謂詞推入,比如內連接,但是視圖定義語句中有union all。
如上面的范例sql:select emp.empno from emp,emp_view_union where emp.empno=emp_view_union.empno1 and emp.ename='FROD';

關于如何理解SQL優化中連接謂詞推入就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

sql
AI

大冶市| 兖州市| 昭觉县| 成安县| 十堰市| 高平市| 股票| 台江县| 昭觉县| 定州市| 竹北市| 平远县| 紫阳县| 榆社县| 鲁山县| 谢通门县| 鄂托克前旗| 浦北县| 岳池县| 额敏县| 林口县| 安义县| 吉安市| 宜州市| 贵港市| 珠海市| 江津市| 元阳县| 汝南县| 肇源县| 凤翔县| 达州市| 白城市| 福安市| 铁岭县| 镇原县| 横峰县| 特克斯县| 绥阳县| 含山县| 凭祥市|