Oracle

日期範圍查詢上的 oracle 性能

  • May 16, 2019

我正在嘗試計算某個組織在某個時間範圍內傳遞的訂單數量。但是我發現下面的查詢(時間範圍為 2 天)比每天執行兩個單獨的查詢要慢得多。

SELECT COUNT(*)  FROM ORDER_HISTORY
WHERE organization = 'BA' AND  TIMESTAMP > = TO_DATE('2016-01-05', 'YYYY-MM-DD') 
AND TIMESTAMP<= TO_DATE('2016-01-05', 'YYYY-MM-DD')+2;

我在列上有一個索引,在列上有timestamps另一個索引organization

在此處輸入圖像描述

這是我的表的架構。該列timestamp的類型為DATE

在此處輸入圖像描述

超過 2 天的查詢執行計劃使用索引 on organization

在此處輸入圖像描述

超過 1 天的查詢執行計劃使用索引 on timestamp

在此處輸入圖像描述

有一些統計數據:

  SELECT COUNT(*)  FROM ORDER_HISTORY
  WHERE ORGANIZATION = 'BA' ;

給出 2359847。

  SELECT COUNT(*)  FROM ORDER_HISTORY
  WHERE TIMESTAMP > = TO_DATE('2016-01-05', 'YYYY-MM-DD')
  AND TIMESTAMP<= TO_DATE('2016-01-05', 'YYYY-MM-DD')+1;

給出 9260。2 天內的相同查詢給出 16510。

為什麼我會得到 oracle DB 引擎的那種奇怪行為?

原因是基於成本的優化器在記憶體中有一個來自先前選擇的計劃,其中給定組織的記錄數(即“LOL”)要小得多,約為 14000。當計劃在記憶體中時,CBO不再關心參數值。採用:

WHERE organization || '' = 'BA'

在我看來,優化器統計資訊要麼已過時,要麼您有數據偏差(即您在 ORGANIZATION 列中有流行和不流行)。優化器估計過濾器ORGANIZATION = 'BA' 返回 14898 行,這與實際結果有很大不同。 dbms_stats.gather_table_stats應該解決這個問題。** 根據螢幕截圖,“LOL”似乎是與組織一起使用的值EXPLAIN,我建議發布實際執行計劃。

您還可以在 2 列(組織、時間戳)上創建擴展統計資訊。

此外,始終檢查實際執行計劃 ( dbms_xplan.display_cursor),而不是explain.

更新

還有一件事可能有助於調查問題。v$sql我還建議在/中查找查詢(或查詢)v$sqlarea並檢查其成本。此外,顯示優化器是否考慮和使用不同計劃的v$sqlhasis_bind_awareis_bind_sensitive列取決於綁定變數的不同值。關於為什么生成多個計劃的其他詳細資訊V$SQL_SHARED_CURSOR系統視圖顯示了現有子游標未與新游標共享的原因。

引用自:https://dba.stackexchange.com/questions/198028