使用
EXECUTION_ENDED_DATE - EXECUTION_START_DATE > interval '40' minute
此外,重寫THI病情
TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE)
到該一個
EXECUTION_START_DATE >= TRUNC(SYSDATE) and EXECUTION_START_DATE < TRUNC(SYSDATE)+1
因爲前者條件阻止Oracle使用上EXECUTION_START_DATE列的索引並帶來了全表掃描
------- --------- 編輯 ----------------
INTERVAL
子句工作s僅用於時間戳算術。
如果查詢返回ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL DAY TO SECOND
,然後更改條件:
EXECUTION_ENDED_DATE - EXECUTION_START_DATE > 40/1440
其中一個「魔術」號1440是在一天(24 * 60)分鐘數。
你能否詳細瞭解爲何阻止Oracle使用索引。
看一個簡單的例子。首先,讓我們建立一個測試dable充滿隨機數據:
CREATE INDEX my_execution_index ON IW_MASTER_LOG(EXECUTION_START_DATE);
最後刷新表和索引的統計信息:
exec DBMS_STATS.gather_table_stats(user, 'IW_MASTER_LOG');
現在檢查
CREATE TABLE IW_MASTER_LOG AS
SELECT sysdate - 500*dbms_random.value as EXECUTION_START_DATE,
t.*
FROM all_objects t;
SELECT count(*) FROM IW_MASTER_LOG;
COUNT(*)
----------
74130
下就EXECUTION_START_DATE
列上創建索引此查詢的執行計劃:
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE EXECUTION_START_DATE >= trunc(sysdate) - 1
AND EXECUTION_START_DATE < trunc(sysdate);
SELECT * FROM table(DBMS_XPLAN.DISPLAY);
Plan hash value: 3519959109
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 149 | 18476 | 152 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| IW_MASTER_LOG | 149 | 18476 | 152 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | MY_EXECUTION_INDEX | 149 | | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TRUNC([email protected]!)>TRUNC([email protected]!)-1)
3 - access("EXECUTION_START_DATE">=TRUNC([email protected]!)-1 AND
"EXECUTION_START_DATE"<TRUNC([email protected]!))
上面的查詢使用索引
現在生成一個查詢,使用您的條件的計劃:
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE trunc(EXECUTION_START_DATE) = trunc(sysdate) ;
SELECT * FROM table(DBMS_XPLAN.DISPLAY);
Plan hash value: 3290956462
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 741 | 91884 | 378 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| IW_MASTER_LOG | 741 | 91884 | 378 (1)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TRUNC(INTERNAL_FUNCTION("EXECUTION_START_DATE"))=TRUNC(SYSDAT
[email protected]!))
俞看到,查詢執行全表掃描 - 在trunct
函數阻止Oracle使用該索引。
正如@АнатолийПредеинsugested:
你可以爲這個列上創建功能指標如創建指數IW_MASTER_LOG(TRUNC(EXECUTION_START_DATE)) id_trunc_esd
他絕對我們來看看他的建議:
CREATE INDEX another_index ON IW_MASTER_LOG(TRUNC(EXECUTION_START_DATE));
exec DBMS_STATS.gather_table_stats(user, 'IW_MASTER_LOG');
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE trunc(EXECUTION_START_DATE) = trunc(sysdate) ;
SELECT * FROM table(DBMS_XPLAN.DISPLAY);
Plan hash value: 1627571743
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 148 | 19536 | 142 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| IW_MASTER_LOG | 148 | 19536 | 142 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | ANOTHER_INDEX | 148 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(TRUNC(INTERNAL_FUNCTION("EXECUTION_START_DATE"))=TRUNC([email protected]!))
完美 - 查詢使用新索引。您可以按照АнатолийПредеин的建議
但是這個指數是有限的 - 它只能服務於trunc(EXECUTION_START_DATE) = ...
條件的查詢。它不能用於在某日期和此日期+ 10分鐘之間挑選行 - 我們仍然需要EXECUTION_START_DATE
列上的普通索引。如果我問我的DBA是否可以創建兩個索引而不是一個索引,因爲我太懶惰了,並且在查詢中重寫了一個條件trunc(date)
,那麼他可能會在地毯上打電話給我。
嗨АнатолийПредеин,感謝您的答覆。該查詢獲取了我想要的結果。你能詳細說明你如何處理會議紀要嗎? –
是不是像..一天已經轉換爲小時,然後幾分鐘? –
當你的日期減去日期這個回報是這兩個日期之間的天數,這就是爲什麼,我乘以24的價值獲得小時,然後在60分鐘獲得。 –