常數複合索引應用案例
從一個客戶的真實最佳化案例引申的問題。
客戶的一個資料庫需要進行最佳化,不過由於程式開發方沒有介入,因此這次最佳化無法對SQL進行修改。
僅對資料庫級的調整一般來說收效不大,不過發現客戶資料庫中個別的SQL存在效能問題,且這個效能問題已經影響到整個資料庫。如果可以將這個SQL最佳化,那麼可以解決目前資料庫的效能問題。幸運的是,這個問題可以透過新增索引來進行最佳化。
模擬問題SQL如下:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 – Production
SQL> create table t (id number not null, created date, other char(200));
Table created.
SQL> insert into t select rownum, created, 'a' from all_objects;
31126 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(user, 'T')
PL/SQL procedure successfully completed.
SQL> var v_id number
SQL> var v_date varchar2(14)
SQL> explain plan for
2
select count(*)
3
from t
4
where nvl(created, sysdate) > to_date(:v_date, 'yyyymmddhh24miss') -
3
5
and id = :v_id;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation |
Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
13 | 92 |
| 1 |
SORT AGGREGATE | | 1 |
13 | |
|* 2 |
TABLE ACCESS FULL | T |
1 | 13 | 92 |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(NVL("T"."CREATED",SYSDATE@!)>TO_DATE(:Z,'yyyymmddhh24miss')-3 AND "T"."ID"=TO_NUMBER(:Z))
Note: cpu costing is off
16 rows selected.
對於這個SQL,透過索引方式最佳化很簡單,只需要建立ID和CREATED上的複合索引,就可以避免全表掃描:
SQL> create index ind_t_id_created on t (id, created);
Index created.
SQL> explain plan for
2
select count(*)
3
from t
4
where nvl(created, sysdate) > to_date(:v_date, 'yyyymmddhh24miss') -
3
5
and id = :v_id;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
--------------------------------------------------------------------------
| Id | Operation |
Name | Rows | Bytes | Cost |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
13 | 2 |
| 1 |
SORT AGGREGATE | | 1 |
13 | |
|* 2 |
INDEX RANGE SCAN |
IND_T_ID_CREATED | 1 |
13 | 2 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 -
access("T"."ID"=TO_NUMBER(:Z))
filter(NVL("T"."CREATED",SYSDATE@!)>TO_DATE(:Z,'yyyymmddhh24miss')-3)
Note: cpu costing is off
17 rows selected.
Oracle之所以可以選擇索引掃描,是由於複合索引中CREATED列為空的記錄也會被儲存。由於ID列為非空,而索引不會儲存所有列全為空的情況,因此CREATED為空的記錄同樣可以在索引中找到。
事實上,即使ID不為空,由於另一個查詢條件指定了ID = :V_ID,這使得訪問的記錄並不包括ID為空的記錄,這使得複合索引仍然可以包括這個SQL需要訪問的所有資料。
不過新的疑問來了,如果查詢的SQL不包含ID列的限制條件,則目前的索引不在可用:
SQL> alter table t modify id null;
Table altered.
SQL> explain plan for
2
select count(*)
3
from t
4
where nvl(created, sysdate) > to_date(:v_date, 'yyyymmddhh24miss') -
3;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation |
Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
8 | 92 |
| 1 |
SORT AGGREGATE | | 1 |
8 | |
|* 2 |
TABLE ACCESS FULL | T |
1556 | 12448 | 92 |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(NVL("T"."CREATED",SYSDATE@!)>TO_DATE(:Z,'yyyymmddhh24miss')-3)
Note: cpu costing is off
16 rows selected.
針對這種情況,一種方法是找一個不為空的欄位做聯合索引,而更省空間的方法是建立複合常數索引:
SQL> create index ind_t_created0 on t(created, 0);
Index created.
SQL> explain plan for
2
select count(*)
3
from t
4
where nvl(created, sysdate) > to_date(:v_date, 'yyyymmddhh24miss') -
3;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
-------------------------------------------------------------------------
| Id | Operation |
Name | Rows | Bytes | Cost |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT |
| 1 |
8 | 4 |
| 1 |
SORT AGGREGATE | | 1 |
8 | |
|* 2 |
INDEX FAST FULL SCAN| IND_T_CREATED0
| 1556 | 12448 | 4 |
-------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(NVL("T"."CREATED",SYSDATE@!)>TO_DATE(:Z,'yyyymmddhh24miss')-3)
Note: cpu costing is off
16 rows selected.
最終透過建立一個包含常數的複合索引,從而避免了這個SQL的全表掃描。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-695801/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQLT 最佳化SQL 用複合索引代替單列索引的案例SQL索引
- 一個複合索引的優化案例索引優化
- MySQL複合索引MySql索引
- SQL優化案例一則--複合索引沒有被使用SQL優化索引
- MySQL複合索引探究MySql索引
- MySQL建立複合索引MySql索引
- SQL最佳化案例一則--複合索引沒有被使用SQL索引
- MongoDB複合索引詳解MongoDB索引
- SUM優化(複合索引)優化索引
- DataFrame刪除複合索引索引
- oracle複合索引介紹(多欄位索引)Oracle索引
- MongoDB中複合索引結構MongoDB索引
- ORACLE 9i資料庫優化案例(2) --- 單列索引變複合索引的優化Oracle資料庫優化索引
- 常見的並聯諧振應用案例
- 複合索引與函式索引優化一例索引函式優化
- 設計複合應用程式:元件設計元件
- 設計複合應用程式:設計模式設計模式
- [應用案例]OT應用案例之dasdig
- Oracle複合索引的建立和注意事項Oracle索引
- 又一個複合索引的SQL調優索引SQL
- 索引設計(組合索引適用場景)索引
- 在Lotus Notes 8 中開發複合應用
- 在 Lotus Notes 複合應用中整合 Lotus Symphony
- 在 Lotus Notes 8 中開發複合應用
- HarmonyOS NEXT應用開發之異常處理案例
- 查詢中讓優化器使用複合索引優化索引
- 「生產事故」MongoDB複合索引引發的災難MongoDB索引
- 增加複合索引優化SQL的簡單過程索引優化SQL
- 複合材料在前述行業的輕量化結構應用行業
- 應用案例IT導彈
- AIGC應用案例AIGC
- 15.7 冪級數在組合數學中的應用
- SAP Fiori應用索引大全索引
- 故障案例:MySQL唯一索引有重複值,官方卻說This is not a bugMySql索引
- oracle goldengate 複製端延時應用引數OracleGo
- Kubernetes 中的應用引數配置案例詳析
- 兩列複合索引中(交換索引中列的順序),選索引的原則是?因為索引名字ascii碼小?索引ASCII
- 蘋果調整應用收費政策:不再對合並的iOS和Mac應用重複收費蘋果iOSMac