Oracle

Oracle 忽略索引

  • November 27, 2013

我有一個感測器數據表,簡化後如下所示:

DEVICE_ID NUMBER
SENSOR_ID NUMBER
DATA_TIME NUMBER
DATA_VALUE1 NUMBER

該表包含數十億行並按週數分區,DATA_TIME 採用 Unix 時間(自 1970 年以來的毫秒數)。我在這個表上有兩個索引,IX1 在 (DATA_TIME DESC) 和 IX2 在 (DEVICE_ID,SENSOR_ID,DATA_TIME)。IX2 是昨天創建的。

我的查詢想要查看當月一個感測器的數據,如下所示:

SELECT /*+ PARALLEL (12) */
  data_time,
  data_value1
FROM table
WHERE device_id = 1041
 AND sensor_id = 202
 AND data_time BETWEEN 1383304859 *1000 AND 1385464859 *1000
ORDER BY data_time ASC 

我驚訝地發現優化器忽略了 IX2 並提出了以下計劃:

---------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name                         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                              |    65 |  1365 |     5  (20)| 00:00:01 |       |       |        |      |            |
|   1 |  PX COORDINATOR                         |                              |       |       |            |          |       |       |        |      |            |
|   2 |   PX SEND QC (ORDER)                    | :TQ10001                     |    65 |  1365 |     5  (20)| 00:00:01 |       |       |  Q1,01 | P->S | QC (ORDER) |
|   3 |    SORT ORDER BY                        |                              |    65 |  1365 |     5  (20)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE                          |                              |    65 |  1365 |     4   (0)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   5 |      PX SEND RANGE                      | :TQ10000                     |    65 |  1365 |     4   (0)| 00:00:01 |       |       |  Q1,00 | P->P | RANGE      |
|   6 |       PX PARTITION RANGE ITERATOR       |                              |    65 |  1365 |     4   (0)| 00:00:01 |   252 |   256 |  Q1,00 | PCWC |            |
|*  7 |        TABLE ACCESS BY LOCAL INDEX ROWID| table                        |    65 |  1365 |     4   (0)| 00:00:01 |   252 |   256 |  Q1,00 | PCWP |            |
|*  8 |         INDEX RANGE SCAN                | ix1                          |     1 |       |     4   (0)| 00:00:01 |   252 |   256 |  Q1,00 | PCWP |            |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

  7 - filter("DEVICE_ID"=1041 AND "SENSOR_ID"=202)
  8 - access(SYS_OP_DESCEND("DATA_TIME")>=HEXTORAW('38FDD8C8BEA9A4FF')  AND SYS_OP_DESCEND("DATA_TIME")<=HEXTORAW('38FDD8DDFAA9A4FF') )
      filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("DATA_TIME"))>=1383304859000 AND SYS_OP_UNDESCEND(SYS_OP_DESCEND("DATA_TIME"))<=1385464859000)

Note
-----
  - automatic DOP: skipped because of IO calibrate statistics are missing

表和索引的統計資訊是最近的。我找到了一些為此語句創建的 SQL 基線並將它們刪除。最重要的是,SQL 調整顧問建議在 (DEVICE_ID,SENSOR_ID,DATA_TIME,DATA_VALUE1) 上創建一個索引。

我通過刪除並重新創建 IX1 解決了這個問題。(其背後的原因是使仍在使用它的任何記憶體計劃無效。)查詢現在在 11 秒後返回 420 行。如果有人可以就發生的事情給我一個很好的理論,我會接受它作為正確答案。

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