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?- 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]
- 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值的情形可能產生全表掃描的情形不演示
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?- --先來做幾個實驗
- 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
- --下面使用提示來強制優化器走索引掃描
- [email protected]> alter system flush buffer_cache;
- [email protected]> select /*+ index(big_table big_table_pk) */ sum(object_id),avg(object_id)
- 2 from big_table where id between 20000 and 50000;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 3098837282
- ---------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ---------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 18 | 511 (1)| 00:00:07 |
- | 1 | SORT AGGREGATE | | 1 | 18 | | |
- | 2 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 30012 | 527K| 511 (1)| 00:00:07 |
- |* 3 | INDEX RANGE SCAN | BIG_TABLE_PK | 30012 | | 64 (0)| 00:00:01 |
- ---------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - access("ID">=20000 AND "ID"<=50000)
- Statistics
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 526 consistent gets
- 526 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
- --注意觀察每一次測試時所耗用的物理讀與邏輯讀
- --從上面的測試可以看出,當表上所返回的資料行數接近於表上的30%時,Oracle 傾向於使用全表掃描
- --而對於表上所返回的資料行數接近於表上的30%的情形,我們給與索引提示,此時比全表掃描更高效,即全表掃描是低效的
- --筆者同時測試了資料返回總行數接近80%的情形以及建立了一個百萬記錄的進行對比測試
- --大致結論,如果查詢所返回的資料的總行數僅僅是表上資料的百分之八十以下,而使用了全表掃描,即可認為該全表掃描是低效的
- --注:
- --具體情況需要具體分析,如果你的表是千萬級的,返回總資料的百分之零點幾都會導致很大的差異
- --其次,表上的索引應具有良好的聚簇因子,如不然,測試的結果可能有天壤之別
- --最後,上面所描述的返回總行數應與執行結果返回的行數有差異,是指多少行參與了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