1. 理解ROWID
ROWID是由Oracle自動加在表中每行最後的一列僞列,既然是僞列,就說明表中並不會物理存儲ROWID的值;你能夠像使用其它列同樣使用它,只是不能對該列的值進行增、刪、改操做;一旦一行數據插入後,則其對應的ROWID在該行的生命週期內是惟一的,即便發生行遷移,該行的ROWID值也不變。
SELECT t.rowid,t.* FROM DM_COMM_PREM_LIST t where LIST_ID= '3106355531';
2. SQL優化器優化方式
1)基於規則的優化器RBO(Rule-Based Optimization)
RBO有嚴格的使用規則,只要按照這套規則去寫SQL語句,不管數據表中的內容怎樣,也不會影響到你的執行計劃;換句話說,RBO對數據「不敏感」,它要求SQL編寫人員必需要了解各項細則;RBO一直沿用至ORACLE 9i,從ORACLE 10g開始,RBO已經完全被拋棄。
2)基於成本的優化器CBO(Cost-Based Optimization)
CBO是一種比RBO更加合理、可靠的優化器,在ORACLE 10g中徹底取代RBO;CBO經過計算各類可能的執行計劃的「代價」,即COST,從中選用COST最低的執行方案做爲實際運行方案;它依賴數據庫對象的統計信息,統計信息的準確與否會影響CBO作出最優的選擇,也就是對數據「敏感」。
3. 基於SQL優化器建立有效複合索引
3.1)INDEX SKIP SCAN(複合索引之索引跳躍掃描)
Oracle 9i後提供,有時候複合索引的前導列(索引包含的第一列)沒有在查詢語句中出現,oralce也會使用該複合索引,
這時候就使用的INDEX SKIP SCAN;
3.2)何時會觸發 INDEX SKIP SCAN
前提條件:表有一個複合索引,且在查詢時有除了前導列(索引中第一列)外的其餘列做爲條件,而且優化器模式爲CBO時當Oracle發現前導列的惟一值個數不多時,會將每一個惟一值都做爲常規掃描的入口,在此基礎上作一次查找,最後合併這些查詢;
例如:
假設表emp有ename(僱員名稱)、job(職位名)、sex(性別)三個字段,而且創建瞭如 create index idx_emp on emp (sex, ename, job) 的複合索引;由於性別只有 '男' 和 '女' 兩個值,因此爲了提升索引的利用率,Oracle可將這個複合索引拆成 ('男', ename, job),('女', ename, job)這兩個複合索引;當查詢 select * from emp where job = 'Programmer' 時該查詢發出後: Oracle先進入sex爲'男'的入口,這時候使用到了 ('男', ename, job) 這條複合索引,查找 job = 'Programmer' 的條目;再進入sex爲'女'的入口,這時候使用到了 ('女', ename, job) 這條複合索引,查找 job = 'Programmer' 的條目;最後合併查詢到的來自兩個入口的結果集。
3.3)建立知足索引跳躍掃描條件的複合索引(含日期字段)後,可是查看執行計劃卻發現並未走複合索引
如:建立索引跳躍掃描 create index IDX_DM_FINISHTIME_ORGANID on DM_COMM_PREM_LIST (FINISH_TIME,ORGAN_ID) ;
查詢執行計劃以下圖,發現未會走複合索引
如何解決此問題:修改日期設定的格式T1.FINISH_TIME >= TO_DATE('2017-06-01', 'yyyy-mm-ddhh24miss') AND T1.FINISH_TIME <= TO_DATE('2017-06-23', 'yyyy-mm-ddhh24miss');經過將傳入參數格式化成對應yyyy-mm-ddhh24miss格式字符串,這樣由Oracle將字符串轉成Date類型,就很順利的走索引區間掃描。效果以下:html
參看博文:http://programdolt.iteye.com/blog/1186690
4.不走索引的緣由,大概有以下8種:
1)創建組合索引,但查詢謂詞並未使用組合索引的第一列,此處有一個INDEX SKIP SCAN概念。
2)在包含有null值的table列上創建索引,當時使用select count(*) from table時不會使用索引。
3)在索引列上使用函數時不會使用索引,若是必定要使用索引只能創建函數索引。
如:Where條件中對字段增長處理函數將不使用該列的索引
select * from emp where to_char(hire_date,'yyyymmdd')='20080411' (不使用)
select * from emp where hire_date = to_char('20080411','yyyymmdd') (使用)
4)當被索引的列進行隱式的類型轉換時不會使用索引。數據庫
示例1:oracle
select * from t where indexed_column = 5,而indexed_column列創建索引但類型是字符型,這時Oracle會產生隱式的類型轉換,轉換後的語句相似於select * from t where to_number(indexed_column) = 5,此時不走索引的狀況相似於case3函數
示例2:日期轉換也有相似問題
select * from t where trunc(date_col) = trunc(sysdate)其中date_col爲索引列,這樣寫不會走索引,可改寫成select * from t where date_col >= trunc(sysdate) and date_col < trunc(sysdate+1),此查詢會走索引。
5)並非全部狀況使用索引都會加快查詢速度,full scan table 有時會更快,尤爲是當查詢的數據量佔整個表的比重較大時,由於full scan table採用的是多塊讀,
當Oracle優化器沒有選擇使用索引時不要當即強制使用,要充分證實使用索引確實查詢更快時再使用強制索引。
6)<>
7)like’%dd’百分號在前
8)not in ,not exist優化
oracle中的索引掃描共計5種,本章只介紹INDEX SKIP SCAN(索引跳躍掃描),其餘四種索引掃描會在另外章節總結。
INDEX UNIQUE SCAN(索引惟一掃描)
INDEX RANGE SCAN(索引範圍掃描)
INDEX FULL SCAN(索引全掃描)
INDEX FAST FULL SCAN(索引快速掃描)
參看博文:
https://www.cnblogs.com/sthinker/p/6080307.html
https://www.cnblogs.com/Dreamer-1/p/6076440.htmlspa