【问题标题】:Oracle Timestamp index very slowOracle 时间戳索引非常慢
【发布时间】:2014-05-29 15:01:02
【问题描述】:

我有这张桌子:

CREATE TABLE "TEST"."TEST_REQUESTS"
  (
    "REQUEST_ID" NUMBER(*,0) NOT NULL ENABLE,
    "RECEPTION_TIME" TIMESTAMP (6) NOT NULL ENABLE,
    "OPERATION" VARCHAR2(25 BYTE) NOT NULL ENABLE,
    "XML_HEADER_IN" CLOB,
    "XML_BODY_IN" CLOB NOT NULL ENABLE,
    "STATUS_ID" NUMBER(*,0) NOT NULL ENABLE,
    "CUSTOMER"  VARCHAR2(25 BYTE)
  )

它有 2 个索引:

CREATE INDEX "TEST"."TEST_REQUESTS_STATUS_IDX" ON "TEST"."TEST_REQUESTS"
    (
      "STATUS_ID" DESC
    )
CREATE INDEX "TEST"."TEST_REQUESTS_TIME_IDX" ON "TEST"."TEST_REQUESTS"
    (
      "RECEPTION_TIME"
    )

我也有一个或多或少这样的程序:

PROCEDURE TEST_LoadHistoryRequestRange (diasMantenidosIN IN number, [...] numRequestOut OUT number [...]) IS

tsStartLimit TIMESTAMP;

BEGIN

tsStartLimit := sysdate - diasMantenidosIN;

SELECT count(REQUEST_ID) into numRequestOut FROM TEST_REQUESTS WHERE STATUS_ID=0 and RECEPTION_TIME<tsStartLimit;

[...]

END;

现在该表已增长到近 1500 万个寄存器...但是,花费近 10 分钟的时间来制作简单的COUNT 是否合乎逻辑?这有什么问题?

非常感谢!!

编辑:这是选择计数的解释计划:

Plan hash value: 378939817

----------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                           |     1 |    14 |     4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE              |                           |     1 |    14 |            |          |
|*  2 |   TABLE ACCESS BY INDEX ROWID| TEST_REQUESTS             |  1125 | 15750 |     4   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | TEST_REQUESTS_STATUS_IDX  |     1 |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------

【问题讨论】:

  • 数据的分布是什么,尤其是status_id 以及时间戳?使用任一索引(或 Gordon 的新索引)的选择性如何?您可以为当前查询添加解释计划吗?无论选择何种访问路径,10 分钟来计算 1500 万行的子集听起来仍然很高。
  • @AlexPoole 我刚刚粘贴了解释计划。您所说的“数据分布”是什么意思?我真的不知道如何回答你的问题,我还是 oracle 的新手。

标签: sql oracle date count timestamp


【解决方案1】:

这可能需要很长时间。您查询的最佳索引是复合索引:

CREATE INDEX "TEST"."TEST_STATUS_REQUESTS_TIME_IDX" ON "TEST"."TEST_REQUESTS"
    (
      STATUS,
      "RECEPTION_TIME",
      REQUEST_ID
    );

请注意,索引中列的顺序会有所不同。

【讨论】:

  • 我刚刚创建了该索引,但它仍在使用 TEST_REQUESTS_STATUS_IDX(我使用了“解释计划”)。我应该删除旧索引吗?
  • @lozan 。 . .如果合适的话,Oracle 应该足够聪明地使用这个索引。 . .如果统计数据是最新的。如果您删除其他索引(或者如果您在查询中使用提示),您可能会强制使用此索引。
  • 我刚刚更新了我的统计数据:EXEC dbms_stats.gather_schema_stats('TEST', cascade=>TRUE);但它仍在使用其他索引...
  • 这是我与提示一起使用的解释计划:explain plan for SELECT /*+ INDEX(TEST_REQUESTS TEST_STATUS_REQUESTS_TIME_IDX) */ count(REQUEST_ID) FROM TEST_REQUESTS WHERE STATUS_ID=0 and RECEPTION_TIME
猜你喜欢
  • 2018-10-07
  • 2016-11-10
  • 1970-01-01
  • 2019-03-13
  • 1970-01-01
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多