1. 程式人生 > >Oracle 全表掃描及其執行計劃(full table scan)

Oracle 全表掃描及其執行計劃(full table scan)

    全表掃描是Oracle訪問資料庫表是較為常見的訪問方式之一。很多朋友一看到SQL語句執行計劃中的全表掃描,就要考慮對其進行修理一番。全表掃描的存在,的確存在可能優化的餘地。但事實上很多時候全表掃描也並非是最低效的,完全要看不同的情形與場合,任一方式都是有利有弊的,也就是具體情況要具體分析。本文描述了什麼是全表掃描以及何時發生全表掃描,何時全表掃描才低效。
  本文涉及到的相關連結:
     高水位線和全表掃描
     啟用 AUTOTRACE 功能
     Oracle 測試常用表BIG_TABLE
     Oracle db_file_mulitblock_read_count引數

  
1、什麼是全表掃描?
    全表掃描就是掃表表中所有的行,實際上是掃描表中所有的資料塊,因為Oracle中最小的儲存單位是Oracle block。
    掃描所有的資料塊就包括高水位線以內的資料塊,即使是空資料塊在沒有被釋放的情形下也會被掃描而導致I/O增加。
    在全表掃描期間,通常情況下,表上這些相鄰的資料塊被按順序(sequentially)的方式訪問以使得一次I/O可以讀取多個數據塊。
    一次讀取更多的資料塊有助於全表掃描使用更少的I/O,對於可讀取的資料塊被限制於引數DB_FILE_MULTIBLOCK_READ_COUNT。

2、何時發生全表掃描?
    a、表上的索引失效或無法被使用的情形(如對謂詞使用函式、計算、NULL值、不等運算子、型別轉換)
    b、查詢條件返回了整個表的大部分資料                 
    c、使用了並行方式訪問表
    d、使用full 提示
    e、統計資訊缺失時使得Oracle認為全表掃描比索引掃描更高效    
    f、表上的資料塊小於DB_FILE_MULTIBLOCK_READ_COUNT值的情形可能產生全表掃描

3、演示全表掃描的情形

[sql] view plaincopyprint?
  1. a、準備演示環境  
  2. [email protected]select * from v$version where rownum<2;  
  3. BANNER  
  4. --------------------------------------------------------------------------------   
  5. Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production  
  6. --建立表t   
  7. [email protected]
    CREATE TABLE t   
  8.   2  AS  
  9.   3  SELECT rownum AS n, rpad('*',100,'*'AS pad   
  10.   4  FROM dual  
  11.   5  CONNECT BY level <= 1000;  
  12. Table created.  
  13. --新增索引   
  14. [email protected]create unique index t_pk on t(n);  
  15. Index created.  
  16. [email protected]alter table t add constraint t_pk primary key(n) using index t_pk;  
  17. Table altered.  
  18. --收集統計資訊   
  19. [email protected]execute dbms_stats.gather_table_stats('SCOTT','T',cascade=>true);  
  20. PL/SQL procedure successfully completed.  
  21. [email protected]set autot trace exp;  
  22. [email protected]select count(*) from t;   --->count(*)的時候使用了索引快速掃描   
  23. Execution Plan  
  24. ----------------------------------------------------------   
  25. Plan hash value: 454320086  
  26. ----------------------------------------------------------------------   
  27. | Id  | Operation             | Name | Rows  | Cost (%CPU)| Time     |  
  28. ----------------------------------------------------------------------   
  29. |   0 | SELECT STATEMENT      |      |     1 |     2   (0)| 00:00:01 |  
  30. |   1 |  SORT AGGREGATE       |      |     1 |            |          |  
  31. |   2 |   INDEX FAST FULL SCAN| T_PK |  1000 |     2   (0)| 00:00:01 |  
  32. ----------------------------------------------------------------------   
  33. [email protected]set autot off;  
  34. [email protected]alter table t move;  --->進行move table   
  35. Table altered.  
  36. -->move 之後索引失效,如下所示   
  37. [email protected]> @idx_info             
  38. Enter value for owner: scott  
  39. Enter value for table_name: t  
  40. Table Name    INDEX_NAME     CL_NAM               CL_POS STATUS   IDX_TYP         DSCD  
  41. ------------- -------------- -------------------- ------ -------- --------------- ----   
  42. T             T_PK           N                         1 UNUSABLE NORMAL          ASC  
  43. b、索引失效導致全表掃描  
  44. [email protected]set autot trace exp;  
  45. [email protected]select count(*) from t;    
  46. Execution Plan  
  47. ----------------------------------------------------------   
  48. Plan hash value: 2966233522  
  49. -------------------------------------------------------------------   
  50. | Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |  
  51. -------------------------------------------------------------------   
  52. |   0 | SELECT STATEMENT   |      |     1 |     7   (0)| 00:00:01 |  
  53. |   1 |  SORT AGGREGATE    |      |     1 |            |          |  
  54. |   2 |   TABLE ACCESS FULL| T    |  1000 |     7   (0)| 00:00:01 |  
  55. -------------------------------------------------------------------   
  56. [email protected]set autot off;  
  57. [email protected]alter index t_pk rebuild;   -->重建索引   
  58. Index altered.  
  59. [email protected]> @idx_info  
  60. Enter value for owner: scott  
  61. Enter value for table_name: t  
  62. Table Name     INDEX_NAME       CL_NAM               CL_POS STATUS   IDX_TYP         DSCD  
  63. -------------- ---------------- -------------------- ------ -------- --------------- ----   
  64. T              T_PK             N                         1 VALID    NORMAL          ASC  
  65. c、返回了整個表的大部分資料使用了全表掃描  
  66. [email protected]select count(pad) from t where n<=990;  
  67. Execution Plan  
  68. ----------------------------------------------------------   
  69. Plan hash value: 2966233522  
  70. ---------------------------------------------------------------------------   
  71. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  72. ---------------------------------------------------------------------------   
  73. |   0 | SELECT STATEMENT   |      |     1 |   105 |     7   (0)| 00:00:01 |  
  74. |   1 |  SORT AGGREGATE    |      |     1 |   105 |            |          |  
  75. |*  2 |   TABLE ACCESS FULL| T    |   991 |   101K|     7   (0)| 00:00:01 |  
  76. ---------------------------------------------------------------------------   
  77. Predicate Information (identified by operation id):  
  78. ---------------------------------------------------   
  79.    2 - filter("N"<=990)  
  80. --返回小部分資料時,使用的是索引掃描   
  81. [email protected]select count(pad) from t where n<=10;  
  82. Execution Plan  
  83. ----------------------------------------------------------   
  84. Plan hash value: 4270555908  
  85. -------------------------------------------------------------------------------------   
  86. | Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  87. -------------------------------------------------------------------------------------   
  88. |   0 | SELECT STATEMENT             |      |     1 |   105 |     3   (0)| 00:00:01 |  
  89. |   1 |  SORT AGGREGATE              |      |     1 |   105 |            |          |  
  90. |   2 |   TABLE ACCESS BY INDEX ROWID| T    |    10 |  1050 |     3   (0)| 00:00:01 |  
  91. |*  3 |    INDEX RANGE SCAN          | T_PK |    10 |       |     2   (0)| 00:00:01 |  
  92. -------------------------------------------------------------------------------------   
  93. Predicate Information (identified by operation id):  
  94. ---------------------------------------------------   
  95.    3 - access("N"<=10)  
  96. d、使用並行方式訪問表時使用了全表掃描  
  97. [email protected]select /*+ parallel(3) */ count(pad) from t where n<=10;  
  98. Execution Plan  
  99. ----------------------------------------------------------   
  100. Plan hash value: 3126468333  
  101. ----------------------------------------------------------------------------------------------------------------   
  102. | Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |  
  103. ----------------------------------------------------------------------------------------------------------------   
  104. |   0 | SELECT STATEMENT       |          |     1 |   105 |     3   (0)| 00:00:01 |        |      |            |  
  105. |   1 |  SORT AGGREGATE        |          |     1 |   105 |            |          |        |      |            |  
  106. |   2 |   PX COORDINATOR       |          |       |       |            |          |        |      |            |  
  107. |   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |   105 |            |          |  Q1,00 | P->S | QC (RAND)  |  
  108. |   4 |     SORT AGGREGATE     |          |     1 |   105 |            |          |  Q1,00 | PCWP |            |  
  109. |   5 |      PX BLOCK ITERATOR |          |    10 |  1050 |     3   (0)| 00:00:01 |  Q1,00 | PCWC |            |  
  110. |*  6 |       TABLE ACCESS FULL| T        |    10 |  1050 |     3   (0)| 00:00:01 |  Q1,00 | PCWP |            |  
  111. ----------------------------------------------------------------------------------------------------------------   
  112. Predicate Information (identified by operation id):  
  113. ---------------------------------------------------   
  114.    6 - filter("N"<=10)  
  115. Note  
  116. -----   
  117.    - Degree of Parallelism is 3 because of hint  
  118. --Author : Robinson   
  119. --Blog   : http://blog.csdn.net/robinson_0612   
  120. e、使用full提示時使用了全表掃描  
  121. [email protected]select /*+ full(t) */ count(pad) from t where n<=10;  
  122. Execution Plan  
  123. ----------------------------------------------------------   
  124. Plan hash value: 2966233522  
  125. ---------------------------------------------------------------------------   
  126. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  127. ---------------------------------------------------------------------------   
  128. |   0 | SELECT STATEMENT   |      |     1 |   105 |     7   (0)| 00:00:01 |  
  129. |   1 |  SORT AGGREGATE    |      |     1 |   105 |            |          |  
  130. |*  2 |   TABLE ACCESS FULL| T    |    10 |  1050 |     7   (0)| 00:00:01 |  
  131. ---------------------------------------------------------------------------   
  132. Predicate Information (identified by operation id):  
  133. ---------------------------------------------------   
  134.    2 - filter("N"<=10)           
  135. f、統計資訊缺失導致全表掃描的情形  
  136. [email protected]exec dbms_stats.delete_table_stats('SCOTT','T');  
  137. PL/SQL procedure successfully completed.  
  138. [email protected]select count(pad) from t where n<=10;  
  139. Execution Plan  
  140. ----------------------------------------------------------   
  141. Plan hash value: 2966233522  
  142. ---------------------------------------------------------------------------   
  143. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  144. ---------------------------------------------------------------------------   
  145. |   0 | SELECT STATEMENT   |      |     1 |    65 |     7   (0)| 00:00:01 |  
  146. |   1 |  SORT AGGREGATE    |      |     1 |    65 |            |          |  
  147. |*  2 |   TABLE ACCESS FULL| T    |    10 |   650 |     7   (0)| 00:00:01 |  
  148. ---------------------------------------------------------------------------   
  149. Predicate Information (identified by operation id):  
  150. ---------------------------------------------------   
  151.    2 - filter("N"<=10)  
  152. Note  
  153. -----   
  154.    - dynamic sampling used for this statement (level=2)  
  155. --上面的執行計劃使用了全表掃描,而且提示使用了動態取樣,也就是缺乏統計資訊   
  156. --表上的資料塊小於DB_FILE_MULTIBLOCK_READ_COUNT值的情形可能產生全表掃描的情形不演示  
a、準備演示環境
[email protected]> select * from v$version where rownum<2;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

--建立表t
[email protected]> CREATE TABLE t 
  2  AS
  3  SELECT rownum AS n, rpad('*',100,'*') AS pad 
  4  FROM dual
  5  CONNECT BY level <= 1000;

Table created.

--新增索引
[email protected]> create unique index t_pk on t(n);

Index created.

[email protected]> alter table t add constraint t_pk primary key(n) using index t_pk;

Table altered.

--收集統計資訊
[email protected]> execute dbms_stats.gather_table_stats('SCOTT','T',cascade=>true);

PL/SQL procedure successfully completed.

[email protected]> set autot trace exp;
[email protected]> select count(*) from t;   --->count(*)的時候使用了索引快速掃描

Execution Plan
----------------------------------------------------------
Plan hash value: 454320086
----------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE       |      |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| T_PK |  1000 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------

[email protected]> set autot off;
[email protected]> alter table t move;  --->進行move table

Table altered.

-->move 之後索引失效,如下所示
[email protected]> @idx_info           
Enter value for owner: scott
Enter value for table_name: t

Table Name    INDEX_NAME     CL_NAM               CL_POS STATUS   IDX_TYP         DSCD
------------- -------------- -------------------- ------ -------- --------------- ----
T             T_PK           N                         1 UNUSABLE NORMAL          ASC


b、索引失效導致全表掃描
[email protected]> set autot trace exp;
[email protected]> select count(*) from t;  

Execution Plan
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| T    |  1000 |     7   (0)| 00:00:01 |
-------------------------------------------------------------------

[email protected]> set autot off;
[email protected]> alter index t_pk rebuild;   -->重建索引

Index altered.

[email protected]> @idx_info
Enter value for owner: scott
Enter value for table_name: t

Table Name     INDEX_NAME       CL_NAM               CL_POS STATUS   IDX_TYP         DSCD
-------------- ---------------- -------------------- ------ -------- --------------- ----
T              T_PK             N                         1 VALID    NORMAL          ASC


c、返回了整個表的大部分資料使用了全表掃描
[email protected]> select count(pad) from t where n<=990;

Execution Plan
----------------------------------------------------------
Plan hash value: 2966233522
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   105 |     7   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |   105 |            |          |
|*  2 |   TABLE ACCESS FULL| T    |   991 |   101K|     7   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("N"<=990)

--返回小部分資料時,使用的是索引掃描
[email protected]> select count(pad) from t where n<=10;

Execution Plan
----------------------------------------------------------
Plan hash value: 4270555908
-------------------------------------------------------------------------------------
| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |      |     1 |   105 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE              |      |     1 |   105 |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| T    |    10 |  1050 |     3   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | T_PK |    10 |       |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("N"<=10)


d、使用並行方式訪問表時使用了全表掃描
[email protected]> select /*+ parallel(3) */ count(pad) from t where n<=10;

Execution Plan
----------------------------------------------------------
Plan hash value: 3126468333
----------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |   105 |     3   (0)| 00:00:01 |        |      |            |
|   1 |  SORT AGGREGATE        |          |     1 |   105 |            |          |        |      |            |
|   2 |   PX COORDINATOR       |          |       |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |   105 |            |          |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE     |          |     1 |   105 |            |          |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR |          |    10 |  1050 |     3   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|*  6 |       TABLE ACCESS FULL| T        |    10 |  1050 |     3   (0)| 00:00:01 |  Q1,00 | PCWP |            |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   6 - filter("N"<=10)
Note
-----
   - Degree of Parallelism is 3 because of hint
--Author : Robinson
--Blog   : http://blog.csdn.net/robinson_0612


e、使用full提示時使用了全表掃描
[email protected]> select /*+ full(t) */ count(pad) from t where n<=10;

Execution Plan
----------------------------------------------------------
Plan hash value: 2966233522
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   105 |     7   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |   105 |            |          |
|*  2 |   TABLE ACCESS FULL| T    |    10 |  1050 |     7   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("N"<=10)         


f、統計資訊缺失導致全表掃描的情形
[email protected]> exec dbms_stats.delete_table_stats('SCOTT','T');

PL/SQL procedure successfully completed.

[email protected]> select count(pad) from t where n<=10;

Execution Plan
----------------------------------------------------------
Plan hash value: 2966233522
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    65 |     7   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |    65 |            |          |
|*  2 |   TABLE ACCESS FULL| T    |    10 |   650 |     7   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("N"<=10)
Note
-----
   - dynamic sampling used for this statement (level=2)

--上面的執行計劃使用了全表掃描,而且提示使用了動態取樣,也就是缺乏統計資訊
--表上的資料塊小於DB_FILE_MULTIBLOCK_READ_COUNT值的情形可能產生全表掃描的情形不演示

4、全表掃描何時低效?

[sql] view plaincopyprint?
  1. --先來做幾個實驗   
  2. a、演示表上的相關資訊  
  3. [email protected]> @idx_info  
  4. Enter value for owner: scott  
  5. Enter value for table_name: big_table  
  6. Table Name                Index Name                CL_NAM    CL_POS Status   IDX_TYP         DSCD  
  7. ------------------------- ------------------------- --------- ------ -------- --------------- ----   
  8. BIG_TABLE                 BIG_TABLE_PK              ID             1 VALID    NORMAL          ASC  
  9. [email protected]> @idx_stat  
  10. Enter value for input_table_name: big_table  
  11. Enter value for owner: scott  
  12.                                                      AVG LEAF BLKS AVG DATA BLKS  
  13. BLEV IDX_NAME        LEAF_BLKS   DST_KEYS       PER KEY       PER KEY CLUST_FACT LAST_ANALYZED         TB_BLKS    TB_ROWS  
  14. ---- -------------- ---------- ---------- ------------- ------------- ---------- ------------------ ---------- ----------   
  15.    1 BIG_TABLE_PK          208     100000             1             1       1483 20130524 10:45:51        1515     100000  
  16. --資料庫引數設定   
  17. [email protected]> show parameter optimizer_index_  
  18. NAME                                 TYPE        VALUE  
  19. ------------------------------------ ----------- ------------------------------   
  20. optimizer_index_caching              integer     0  
  21. optimizer_index_cost_adj             integer     100  
  22. [email protected]> show parameter optimizer_mode  
  23. NAME                                 TYPE        VALUE  
  24. ------------------------------------ ----------- ------------------------------   
  25. optimizer_mode                       string      ALL_ROWS  
  26. b、查詢返回20%資料行的情形  
  27. [email protected]alter system flush buffer_cache;                                                    
  28. [email protected]select sum(object_id),avg(object_id) from big_table where id between 20000 and 40000;  
  29. Execution Plan  
  30. ----------------------------------------------------------   
  31. Plan hash value: 3098837282                             -- 執行計劃中,使用了索引範圍掃描   
  32. ---------------------------------------------------------------------------------------------   
  33. | Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)| Time     |  
  34. ---------------------------------------------------------------------------------------------   
  35. |   0 | SELECT STATEMENT             |              |     1 |    18 |   341   (0)| 00:00:05 |  
  36. |   1 |  SORT AGGREGATE              |              |     1 |    18 |            |          |  
  37. |   2 |   TABLE ACCESS BY INDEX ROWID| BIG_TABLE    | 20046 |   352K|   341   (0)| 00:00:05 |  
  38. |*  3 |    INDEX RANGE SCAN          | BIG_TABLE_PK | 20046 |       |    43   (0)| 00:00:01 |  
  39. ---------------------------------------------------------------------------------------------   
  40. Predicate Information (identified by operation id):  
  41. ---------------------------------------------------   
  42.    3 - access("ID">=20000 AND "ID"<=40000)  
  43. Statistics  
  44. ----------------------------------------------------------   
  45.           0  recursive calls  
  46.           0  db block gets  
  47.         351  consistent gets  
  48.         351  physical reads  
  49.           0  redo size  
  50.         427  bytes sent via SQL*Net to client  
  51.         349  bytes received via SQL*Net from client  
  52.           2  SQL*Net roundtrips to/from client  
  53.           0  sorts (memory)  
  54.           0  sorts (disk)  
  55.           1  rows processed  
  56. [email protected]alter system flush buffer_cache;   
  57. [email protected]select /*+ full(big_table) */ sum(object_id),avg(object_id) from big_table where id between 20000 and 40000;  
  58. Execution Plan  
  59. ----------------------------------------------------------   
  60. Plan hash value: 599409829                ---- 使用了提示執行為全表掃描   
  61. --------------------------------------------------------------------------------   
  62. | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  63. --------------------------------------------------------------------------------   
  64. |   0 | SELECT STATEMENT   |           |     1 |    18 |   413   (1)| 00:00:05 |  
  65. |   1 |  SORT AGGREGATE    |           |     1 |    18 |            |          |  
  66. |*  2 |   TABLE ACCESS FULL| BIG_TABLE | 20046 |   352K|   413   (1)| 00:00:05 |  
  67. --------------------------------------------------------------------------------   
  68. Predicate Information (identified by operation id):  
  69. ---------------------------------------------------   
  70.    2 - filter("ID"<=40000 AND "ID">=20000)  
  71. Statistics  
  72. ----------------------------------------------------------   
  73.           0  recursive calls  
  74.           0  db block gets  
  75.        1486  consistent gets  
  76.        1484  physical reads  
  77.           0  redo size  
  78.         427  bytes sent via SQL*Net to client  
  79.         349  bytes received via SQL*Net from client  
  80.           2  SQL*Net roundtrips to/from client  
  81.           0  sorts (memory)  
  82.           0  sorts (disk)  
  83.           1  rows processed  
  84. --注意對比上面兩次操作中的consistent gets與physical reads   
  85. c、查詢返回30%資料行的情形  
  86. [email protected]alter system flush buffer_cache;  
  87. [email protected]select sum(object_id),avg(object_id) from big_table where id between 20000 and 50000;  
  88. Execution Plan  
  89. ----------------------------------------------------------   
  90. Plan hash value: 599409829             --->儘管返回資料的總行數為30%,而此時優化器使用了全表掃描   
  91. --------------------------------------------------------------------------------   
  92. | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  93. --------------------------------------------------------------------------------   
  94. |   0 | SELECT STATEMENT   |           |     1 |    18 |   413   (1)| 00:00:05 |  
  95. |   1 |  SORT AGGREGATE    |           |     1 |    18 |            |          |  
  96. |*  2 |   TABLE ACCESS FULL| BIG_TABLE | 30012 |   527K|   413   (1)| 00:00:05 |  
  97. --------------------------------------------------------------------------------   
  98. Predicate Information (identified by operation id):  
  99. ---------------------------------------------------   
  100.    2 - filter("ID"<=50000 AND "ID">=20000)  
  101. Statistics  
  102. ----------------------------------------------------------   
  103.           0  recursive calls  
  104.           0  db block gets  
  105.        1486  consistent gets  
  106.        1484  physical reads  
  107.           0  redo size  
  108.         427  bytes sent via SQL*Net to client  
  109.         349  bytes received via SQL*Net from client  
  110.           2  SQL*Net roundtrips to/from client  
  111.           0  sorts (memory)  
  112.           0  sorts (disk)  
  113.           1  rows processed  
  114. --下面使用提示來強制優化器走索引掃描   
  115. [email protected]alter system flush buffer_cache;  
  116. [email protected]select /*+ index(big_table big_table_pk) */ sum(object_id),avg(object_id)   
  117.   2  from big_table where id between 20000 and 50000;  
  118. Execution Plan  
  119. ----------------------------------------------------------   
  120. Plan hash value: 3098837282  
  121. ---------------------------------------------------------------------------------------------   
  122. | Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)| Time     |  
  123. ---------------------------------------------------------------------------------------------   
  124. |   0 | SELECT STATEMENT             |              |     1 |    18 |   511   (1)| 00:00:07 |  
  125. |   1 |  SORT AGGREGATE              |              |     1 |    18 |            |          |  
  126. |   2 |   TABLE ACCESS BY INDEX ROWID| BIG_TABLE    | 30012 |   527K|   511   (1)| 00:00:07 |  
  127. |*  3 |    INDEX RANGE SCAN          | BIG_TABLE_PK | 30012 |       |    64   (0)| 00:00:01 |  
  128. ---------------------------------------------------------------------------------------------   
  129. Predicate Information (identified by operation id):  
  130. ---------------------------------------------------   
  131.    3 - access("ID">=20000 AND "ID"<=50000)  
  132. Statistics  
  133. ----------------------------------------------------------   
  134.           0  recursive calls  
  135.           0  db block gets  
  136.         526  consistent gets  
  137.         526  physical reads  
  138.           0  redo size  
  139.         427  bytes sent via SQL*Net to client  
  140.         349  bytes received via SQL*Net from client  
  141.           2  SQL*Net roundtrips to/from client  
  142.           0  sorts (memory)  
  143.           0  sorts (disk)  
  144.           1  rows processed  
  145. --注意觀察每一次測試時所耗用的物理讀與邏輯讀   
  146. --從上面的測試可以看出,當表上所返回的資料行數接近於表上的30%時,Oracle 傾向於使用全表掃描   
  147. --而對於表上所返回的資料行數接近於表上的30%的情形,我們給與索引提示,此時比全表掃描更高效,即全表掃描是低效的   
  148. --筆者同時測試了資料返回總行數接近80%的情形以及建立了一個百萬記錄的進行對比測試   
  149. --大致結論,如果查詢所返回的資料的總行數僅僅是表上資料的百分之八十以下,而使用了全表掃描,即可認為該全表掃描是低效的   
  150. --注:   
  151. --具體情況需要具體分析,如果你的表是千萬級的,返回總資料的百分之零點幾都會導致很大的差異   
  152. --其次,表上的索引應具有良好的聚簇因子,如不然,測試的結果可能有天壤之別   
  153. --最後,上面所描述的返回總行數應與執行結果返回的行數有差異,是指多少行參與了sum(object_id)  
--先來做幾個實驗
a、演示表上的相關資訊
[email protected]> @idx_info
Enter value for owner: scott
Enter value for table_name: big_table

Table Name                Index Name                CL_NAM    CL_POS Status   IDX_TYP         DSCD
------------------------- ------------------------- --------- ------ -------- --------------- ----
BIG_TABLE                 BIG_TABLE_PK              ID             1 VALID    NORMAL          ASC

[email protected]> @idx_stat
Enter value for input_table_name: big_table
Enter value for owner: scott

                                                     AVG LEAF BLKS AVG DATA BLKS
BLEV IDX_NAME        LEAF_BLKS   DST_KEYS       PER KEY       PER KEY CLUST_FACT LAST_ANALYZED         TB_BLKS    TB_ROWS
---- -------------- ---------- ---------- ------------- ------------- ---------- ------------------ ---------- ----------
   1 BIG_TABLE_PK          208     100000             1             1       1483 20130524 10:45:51        1515     100000

--資料庫引數設定
[email protected]> show parameter optimizer_index_

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_index_caching              integer     0
optimizer_index_cost_adj             integer     100
[email protected]> show parameter optimizer_mode

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_mode                       string      ALL_ROWS


b、查詢返回20%資料行的情形
[email protected]> alter system flush buffer_cache;                                                  
[email protected]> select sum(object_id),avg(object_id) from big_table where id between 20000 and 40000;

Execution Plan
----------------------------------------------------------
Plan hash value: 3098837282                             -- 執行計劃中,使用了索引範圍掃描
---------------------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    18 |   341   (0)| 00:00:05 |
|   1 |  SORT AGGREGATE              |              |     1 |    18 |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| BIG_TABLE    | 20046 |   352K|   341   (0)| 00:00:05 |
|*  3 |    INDEX RANGE SCAN          | BIG_TABLE_PK | 20046 |       |    43   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("ID">=20000 AND "ID"<=40000)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        351  consistent gets
        351  physical reads
          0  redo size
        427  bytes sent via SQL*Net to client
        349  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

[email protected]> alter system flush buffer_cache; 
[email protected]> select /*+ full(big_table) */ sum(object_id),avg(object_id) from big_table where id between 20000 and 40000;

Execution Plan
----------------------------------------------------------
Plan hash value: 599409829                ---- 使用了提示執行為全表掃描
--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    18 |   413   (1)| 00:00:05 |
|   1 |  SORT AGGREGATE    |           |     1 |    18 |            |          |
|*  2 |   TABLE ACCESS FULL| BIG_TABLE | 20046 |   352K|   413   (1)| 00:00:05 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("ID"<=40000 AND "ID">=20000)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1486  consistent gets
       1484  physical reads
          0  redo size
        427  bytes sent via SQL*Net to client
        349  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

--注意對比上面兩次操作中的consistent gets與physical reads


c、查詢返回30%資料行的情形
[email protected]> alter system flush buffer_cache;
[email protected]> select sum(object_id),avg(object_id) from big_table where id between 20000 and 50000;

Execution Plan
----------------------------------------------------------
Plan hash value: 599409829             --->儘管返回資料的總行數為30%,而此時優化器使用了全表掃描
--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    18 |   413   (1)| 00:00:05 |
|   1 |  SORT AGGREGATE    |           |     1 |    18 |            |          |
|*  2 |   TABLE ACCESS FULL| BIG_TABLE | 30012 |   527K|   413   (1)| 00:00:05 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("ID"<=50000 AND "ID">=20000)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1486  consistent gets
       1484  physical reads
          0  redo size
        427  bytes sent via SQL*Net to client
        349  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

--下面使用提示來強制優化器走索引掃描

            
           

相關推薦

Oracle 掃描及其執行計劃(full table scan)

    全表掃描是Oracle訪問資料庫表是較為常見的訪問方式之一。很多朋友一看到SQL語句執行計劃中的全表掃描,就要考慮對其進行修理一番。全表掃描的存在,的確存在可能優化的餘地。但事實上很多時候全表掃描也並非是最低效的,完全要看不同的情形與場合,任一方式都是有利有弊的,也就是具體情況要具體分析。本文描述了

oracle 掃描和索引掃描

1) 全表掃描(Full Table Scans, FTS)        為實現全表掃描,Oracle讀取表中所有的行,並檢查每一行是否滿足語句的WHERE限制條件。Oracle順序地讀取分配給表的每個資料塊,直到讀到表的最高水線處(high water mark, HWM

Oracle 11g掃描以Direct Path Read方式執行

在Oracle Database 11g中有一個新特性,全表掃描可以通過直接路徑讀的方式來執行(Direct Path Read),這是一個合理的變化,如果全表掃描的大量資料讀取是偶發性的,則直接路徑讀可以避免大量資料對於Buffer Cache的衝擊。當然對於小表來說,Oracle允許通過Buffer C

ORACLE sql調優之記錄一次trim函數引發的大掃描

oracle trim 全表掃描 sql 調優 2017年8月14日,一地市oracle相關的調度程序ETL抽取速度奇慢,sql語句每次執行平均時間要9秒左右,如果所示:該調度過程涉及的sql語句如下:select count(*) from (SELECT rtrim(

Oracle 檢查資料庫有哪些頻繁進行掃描

select a.object_name, a.sql_id, b.sql_text, max(b.executions) executions, max(b.last_active_time) last_active_time, b.first_load_time from v$sql_plan a,

Oracle SQL優化必要的掃描思路分析

大多數情況下,我們需要避免SQL在查詢時進行全表掃描(FTS),但是對於必須需要進行全表掃描的情況,也可以進行一些優化處理。 即使全表掃描是檢索所需資料的唯一可行方法,仍然有多種方法來提升查詢效能。優化掃描的技術包括: 1、  通過讓表變小來減少掃描所需的邏輯塊讀取的數量

oracle select 走索引?走掃描

1. 對返回的行無任何限定條件,即沒有where 子句 2. 未對資料表與任何索引主列相對應的行限定條件 例如:在City-State-Zip列建立了三列複合索引,那麼僅對State列限定條件不能使用這個索引,因為State不是索引的主列。 3. 對索引的主列有限定條件,但是在條件表示式裡使用以下表達式

避免掃描的sql優化

設計 結束 edate bstr 需要 表達 大量數據 第一個 關鍵字 摘抄自:http://www.cnblogs.com/jameslif/p/6406167.html 對查詢進行優化,應盡量避免全表掃描,首先應考慮在where 及order by 涉及的列上建立索引

項目owner看這裏,MaxCompute掃描新功能,給你“失誤”的機會

業務需求 機會 表數據 人的 人員 做了 設置 cli ssi 摘要: MaxCompute發布了“ALIAS 命令”,提供了在不修改代碼的前提下,在MapReduce或自定義函數(UDF) 代碼中,通過某個固定的資源名讀取不同資源(數據)的需求。隨著社會數據收集手段的不斷

造成MySQL掃描的原因

記錄 添加 its 工程師 review 全表掃描 字段 count 查詢條件 全表掃描是數據庫搜尋表的每一條記錄的過程,直到所有符合給定條件的記錄返回為止。通常在數據庫中,對無索引的表進行查詢一般稱為全表掃描;然而有時候我們即便添加了索引,但當我們的SQL語句寫的不合理的

關係型資料庫掃描分片詳解

導讀:資料匯流排(DBus)專注於資料的實時採集與實時分發,可以對IT系統在業務流程中產生的資料進行匯聚,經過轉換處理後成為統一JSON的資料格式(UMS),提供給不同資料使用方訂閱和消費,充當數倉平臺、大資料分析平臺、實時報表和實時營銷等業務的資料來源。在上一篇關於DBus的文章中,我們主要介紹了在DBus

ORACLE-介紹空間及其的建立以及在空間下使用者的建立

什麼是表空間: ORACLE資料庫被劃分成稱作為表空間的邏輯區域——形成ORACLE資料庫的邏輯結構。一個ORACLE資料庫能夠有一個或多個表空間,而一個表空間則對應著一個或多個物理的資料庫檔案。表空間是ORACLE資料庫恢復的最小單位,容納著許多資料庫實體,如表、檢視、索引、聚簇、回退段和臨時

Oracle效能優化-讀懂執行計劃

Oracle的執行計劃 得到執行計劃的方式 Autotrace例子

MyBatis實戰之對映器 SSM框架之批量增加示例(同步請求jsp檢視解析) mybatis的批量更新例項 造成MySQL掃描的原因 SSM框架實戰之整合EhCache

對映器是MyBatis最強大的工具,也是我們使用MyBatis時用得最多的工具,因此熟練掌握它十分必要。MyBatis是針對對映器構造的SQL構建的輕量級框架,並且通過配置生成對應的JavaBean返回給呼叫者,而這些配置主要便是對映器,在MyBatis中你可以根據情況定義動態SQL來滿足不同場景的需要,它比

Mysql避免掃描的sql查詢優化

對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引:  嘗試下面的技巧以避免優化器錯選了表掃描:   使用ANALYZE TABLE tbl_

scala操作Hbas -掃描

package com.blm.util import javax.ws.rs.core.Response.Status.Family import org.apache.hadoop.hbase.{CellUtil, HBaseConfiguration, TableName} im

如何對10億資料量級的mongoDB作高效的掃描

本文連結: http://quentinXXZ.iteye.com/blog/2149440 一、正常情況下,不應該有這種需求 首先,大家應該有個概念,標題中的這個問題,在大多情況下是一個偽命題,不應該被提出來。要知道,對於一般較大資料量的資料庫,全表查詢,這種操作一般情況下是不應該出現的,在做正常查

MySQL查詢優化之避免掃描

原文地址:https://dev.mysql.com/doc/refman/5.7/en/table-scan-avoidance.html 譯文: 8.2.1.20 避免全表掃描 當MySQL使用全表掃描來解析查詢時,EXPLAIN的輸出結果中將在type列顯示ALL。這種情況通常發生

索引 vs 掃描

之前我們介紹了第一個檔案格式: 在這個檔案格式裡,資料沒有排序,順序儲存,我們只提供了查詢所有資料的介面,當我們想進行值過濾時,比如查詢大於10的資料,需要將所有資料遍歷一遍,如果把這個檔案看做一個只有一列的表,這種查詢方式就叫全表掃描。 磁碟結構和

HBase 帶有過濾條件的掃描 小計

 HBase 帶有過濾條件的全表掃描     字首過濾器     列名過濾器     時間戳過濾器     組合過濾器 scan 'demo_table' , {     FILTER