Oracle
為什麼對 max() 查詢進行索引範圍掃描?
我有一個記錄數據傳輸到另一個系統的表。
create table transfer_log (id number(10), fk_data number(10), first_sent_time date, last_sent_time date, transfer_status number(3), error_message varchar2(250)); create unique index pk_transfer_log on transfer_log (id); alter table transfer_log add constraint pk_transfer_log primary key (id); create index idx_transfer_log_status on transfer_log (transfer_status, last_sent_time desc);
transfer_status 列儲存來自發送數據的 HTTP 狀態。transfer_status 永遠不會為空(最初為 0),last_sent_time 最初為空。所以我進行了一次健康檢查,看看上次成功傳輸的時間是:
select max(d.last_sent_time) from transfer_log d where d.transfer_status = 200 ;
我希望索引能讓這個查詢更快。但現在已經接近 1 秒,執行計劃看起來不太好:
---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 2624 | | | 1 | SORT AGGREGATE | | 1 | 6 | | | | 2 | INDEX RANGE SCAN | IDX_TRANSFER_LOG_STATUS | 1272670 | 7636020 | 2624 | | ----------------------------------------------------------------------------------------
我希望索引(尤其是使用遞減的 last_sent_time)可以使這個查詢更快,因為只需要讀取第一個條目。
我做錯什麼了?
刪除該索引並在沒有 desc 的情況下創建:
create index idx_transfer_log_status on transfer_log (transfer_status, last_sent_time);
數據庫可以決定以降序讀取升序索引。最後一個條目的讀取速度與第一個條目一樣快。
但更好的是,當您搜尋 MIN/MAX 值並使用該操作時,它可以辨識一個案例:
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID 6q8sbnqkajz74, child number 1 ------------------------------------- select max(d.last_sent_time) from transfer_log d where d.transfer_status = 200 Plan hash value: 3076158531 -------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 2 (100)| | | 1 | SORT AGGREGATE | | 1 | 11 | | | | 2 | FIRST ROW | | 1 | 11 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN (MIN/MAX)| IDX_TRANSFER_LOG_STATUS | 1 | 11 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("D"."TRANSFER_STATUS"=200)
不幸的是,這不適用於
desc
索引。