高效的SQL(index range scan優化排序)
高效的SQL(index range scan優化排序)
一、 實驗表
表的結構、內容、索引(Data is returned in the ascending order of index columns. Multiple rows with identical values are sorted in ascending order by rowid.)
doudou@TEST> desc range_scan
Name Null? Type
----------------------------------------------------- -------- ------------------------------------
ID NUMBER
NAME VARCHAR2(20)
SUM VARCHAR2(20)
doudou@TEST> select * from range_scan;
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
2 doudou+2 3
3 doudou+3 3
4 doudou+4 3
5 doudou+5 4
6 doudou+6 4
7 doudou+7 4
8 doudou+8 5
9 doudou+9 5
10 doudou+10 6
11 doudou+11 6
12 doudou+12 6
11 rows selected.
doudou@TEST> select index_name,column_name,table_name from user_ind_columns where table_name='RANGE_SCAN';
INDEX_NAME COLUMN_NAME TABLE_NAME
------------------------------ ------------------------------ ------------------------------
INDEX_RANGE_SCAN_SUM SUM RANGE_SCAN
二、 開啟執行計劃,執行SQL
The optimizer uses a range scan when it finds one or more leading columns of an index specified in conditions(優化器使用一個範圍掃描當找到一個或多個列的索引指定主要在條件。)
1、例如:sum=’5’; sum>'5';sum '4' and sum
doudou@TEST> select * from range_scan where sum='5';
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
8 doudou+8 5
9 doudou+9 5
Execution Plan
----------------------------------------------------------
Plan hash value: 3049432069
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 2 | 74 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 2 | | 1 (0)| 00:00:01 |
doudou@TEST> select * from range_scan where sum>'5';
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
10 doudou+10 6
11 doudou+11 6
12 doudou+12 6
Execution Plan
----------------------------------------------------------
Plan hash value: 3049432069
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 111 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 3 | 111 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 3 | | 1 (0)| 00:00:01 |
doudou@TEST> select * from range_scan where sum;
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
2 doudou+2 3
3 doudou+3 3
4 doudou+4 3
5 doudou+5 4
6 doudou+6 4
7 doudou+7 4
6 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3049432069
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 222 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 6 | 222 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 6 | | 1 (0)| 00:00:01 |
doudou@TEST> select * from range_scan where sum >'4' and sum;
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
8 doudou+8 5
9 doudou+9 5
Execution Plan
----------------------------------------------------------
Plan hash value: 3049432069
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 2 | 74 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 2 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------
2、index range scan使用萬用字元需注意 ‘%5’像這樣,萬用字元在前的不走範圍索引;’5%’萬用字元在最後的正常走範圍索引
doudou@TEST> select * from range_scan where sum like '%5';
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
8 doudou+8 5
9 doudou+9 5
Execution Plan
----------------------------------------------------------
Plan hash value: 1933872984
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| RANGE_SCAN | 2 | 74 | 3 (0)| 00:00:01 |
【使用通配符不恰當,導致不走索引(低效)】
doudou@TEST> select * from range_scan where sum like '5%';
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
8 doudou+8 5
9 doudou+9 5
Execution Plan
----------------------------------------------------------
Plan hash value: 3049432069
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 2 | 74 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 2 | | 1 (0)| 00:00:01 |
【正確的使用萬用字元’5%’,(高效)】
3、當在索引列分組或排序的時候使用範圍掃描,order by 索引列可以避免排序
doudou@TEST> select * from range_scan where sum='5' order by sum;
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
8 doudou+8 5
9 doudou+9 5
Execution Plan
----------------------------------------------------------
Plan hash value: 3049432069
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 2 | 74 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 2 | | 1 (0)| 00:00:01 |
【索引列進行了order by,索引沒有進行更多的sort order by(高效)】
doudou@TEST> select * from range_scan where sum='5' order by id ;
ID NAME SUM
---------- ---------------------------------------- ----------------------------------------
8 doudou+8 5
9 doudou+9 5
Execution Plan
----------------------------------------------------------
Plan hash value: 823340891
----------------------------------------------------------------------------------------------------
-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
----------------------------------------------------------------------------------------------------
-
| 0 | SELECT STATEMENT | | 2 | 74 | 3 (34)| 00:00:01
|
| 1 | SORT ORDER BY | | 2 | 74 | 3 (34)| 00:00:01
|
| 2 | TABLE ACCESS BY INDEX ROWID| RANGE_SCAN | 2 | 74 | 2 (0)| 00:00:01
|
|* 3 | INDEX RANGE SCAN | INDEX_RANGE_SCAN_SUM | 2 | | 1 (0)| 00:00:01
|
----------------------------------------------------------------------------------------------------
【order by id,id不是索引列,這裡又進行了排序,浪費了cost(低效)】
三、 總結
1、index range scan 使用條件:(Data is returned in the ascending order of index columns. Multiple rows with identical values are sorted in ascending order by rowid.)
2、index range scan使用萬用字元需注意: ‘%name’不恰當使用不走索引,’name%’正確使用走索引
3、index range scan優點:group by 或order by 使用索引列這樣就避免了再次sort,提高了效能
附表:
1、實驗資料庫環境
sys@TEST> show parameter optimizer_mode
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
optimizer_mode string ALL_ROWS
sys@TEST> select * from v$version;
BANNER
----------------------------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for Linux: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 – Production
2、官檔
13.5.3.3.1 When the Optimizer Uses Index Range Scans
The optimizer uses a range scan when it finds one or more leading columns of an index specified in conditions, such as the following:
- col1 = :b1
- col1 < :b1
- col1 > :b1
- AND combination of the preceding conditions for leading columns in the index
- col1 like 'ASD%' wild-card searches should not be in a leading position otherwise the condition col1 like '%ASD' does not result in a range scan.
Range scans can use unique or non-unique indexes. Range scans avoid sorting when index columns constitute the ORDER BY/GROUP BY clause.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26442936/viewspace-750465/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 高效的SQL(Index unique scan最優化)SQLIndex優化
- index range scan,index fast full scan,index skip scan發生的條件IndexAST
- Index Range Scan (214)Index
- 高效的SQL(index skip scan使用條件)SQLIndex
- oracle index unique scan/index range scan和mysql range/const/ref/eq_ref的區別OracleIndexMySql
- 索引優化index skip scan索引優化Index
- Index Range Scan成本與10053Index
- [總結]關於index range scans & INDEX (FAST FULL SCAN)IndexAST
- Index Range Scan成本 Histogram 和 10053IndexHistogram
- INDEX RANGE SCAN DESCENDING的邏輯讀問題Index
- 收集full table / index scan sqlIndexSQL
- INDEX UNIQUE SCAN,INDEX FULL SCAN和INDEX FAST FULL SCANIndexAST
- 【優化】INDEX FULL SCAN (MIN/MAX)訪問路徑優化Index
- 【SQL優化】LIKE vs INDEXSQL優化Index
- Index的掃描方式:index full scan/index fast full scanIndexAST
- oracle sql 排序優化OracleSQL排序優化
- rowid,index,INDEX FULL SCAN,INDEX FAST FULL SCAN|IndexAST
- Index Full Scan vs Index Fast Full ScanIndexAST
- Index Full Scan 與 Index Fast Full ScanIndexAST
- INDEX FULL SCAN和INDEX FAST FULL SCAN的區別IndexAST
- index full scan 和 index fast full scan (IFS,FFS)的不同IndexAST
- 高效的SQL(Index-Organized Tables優化精確查詢和範圍查詢)SQLIndexZed優化
- INDEX FULL SCAN和INDEX FAST FULL SCAN區別IndexAST
- index full scan 和 index FAST full scan 區別IndexAST
- Index Full Scan 與 Index Fast Full Scan (Final)IndexAST
- INDEX SKIP SCANIndex
- 高效的SQL(index values與index column values關係?)SQLIndex
- SQL優化之利用索引排序SQL優化索引排序
- Clustered Index Scan and Clustered Index SeekIndex
- sql優化一例(index_desc)SQL優化Index
- 理解index skip scanIndex
- Index Unique Scan (213)Index
- 【TUNE_ORACLE】列出走了INDEX FULL SCAN的SQL參考OracleIndexSQL
- 【TUNE_ORACLE】列出走了INDEX SKIP SCAN的SQL參考OracleIndexSQL
- MySQL SQL優化 - 覆蓋索引(covering index)MySql優化索引Index
- C# 使用 Index 和 Range 簡化集合操作C#Index
- PostgreSQL DBA(119) - pgAdmin(LIMIT:Index Scan vs Bitmap Index Scan)SQLMITIndex
- Index Full Scan和Index Fast Full Scan行為差異分析(上)IndexAST