如何使用这种索引?

时间:2019-04-30 21:20:47

标签: sql oracle plsql oracle11g

我正在尝试使用一种索引类型,因此无法正常工作。也许您可以帮助我意识到我在做错什么。

这是我的表的定义:

CREATE TABLE "TIR"."INT07NCMP"(
    "INT07_CORRELATIVO" NUMBER(10) NOT NULL ENABLE,
    "INT07_CENTRO" VARCHAR2(4 BYTE) NOT NULL ENABLE, 
    "INT07_CODCOMPONENTE" VARCHAR2(18 BYTE) NOT NULL ENABLE, 
    "INT07_ALMCOMPONENTE" VARCHAR2(4 BYTE) NOT NULL ENABLE, 
    "INT07_CANCOMPONENTE" NUMBER(13,3), 
    "INT07_UNICOMPONENTE" VARCHAR2(3 BYTE), 
    "INT07_CODPORTADOR" VARCHAR2(18 BYTE) NOT NULL ENABLE, 
    "INT07_ALMPORTADOR" VARCHAR2(4 BYTE) NOT NULL ENABLE, 
    "INT07_CANPORTADOR" NUMBER(13,3), 
    "INT07_UNIPORTADOR" VARCHAR2(3 BYTE), 
    "INT07_ALMDESTINO" VARCHAR2(4 BYTE) NOT NULL ENABLE, 
    "INT07_FECINICIO" VARCHAR2(10 BYTE) NOT NULL ENABLE, 
    "INT07_HORINICIO" VARCHAR2(8 BYTE) NOT NULL ENABLE,
    "INT07_FECTERMINO" VARCHAR2(10 BYTE) NOT NULL ENABLE, 
    "INT07_HORTERMINO" VARCHAR2(8 BYTE) NOT NULL ENABLE,
    "INT07_ESTPOCH" VARCHAR2(1 BYTE), 
    "INT07_TMPPOCH" TIMESTAMP (6), 
    "INT07_ESTSAP" VARCHAR2(1 BYTE), 
    "INT07_TMPSAP" TIMESTAMP (6), 
    "INT07_TIMESTAMP" TIMESTAMP (6) NOT NULL ENABLE, 
    CONSTRAINT "INT07NCMP_PK" PRIMARY KEY ("INT07_CORRELATIVO"),
    CONSTRAINT "INT07NCMP_UK1" UNIQUE (
        "INT07_CENTRO", "INT07_CODCOMPONENTE", "INT07_ALMCOMPONENTE", "INT07_CODPORTADOR", "INT07_ALMPORTADOR",
        "INT07_FECINICIO", "INT07_HORINICIO", "INT07_FECTERMINO", "INT07_HORTERMINO"
    )
);

这是我创建的索引:

CREATE INDEX "TIR"."INT07NCMP_IDX1" ON "TIR"."INT07NCMP" ("INT07_CENTRO", "INT07_ESTPOCH");
CREATE INDEX "TIR"."INT07NCMP_IDX2" ON "TIR"."INT07NCMP" ("INT07_CENTRO", "INT07_ESTSAP");
CREATE INDEX "TIR"."INT07NCMP_IDX3" ON "TIR"."INT07NCMP" ("INT07_CENTRO", "INT07_CORRELATIVO", "INT07_FECINICIO", "INT07_HORINICIO", "INT07_FECTERMINO", "INT07_HORTERMINO");

使用“解释计划”对索引1和2很好,但对索引3不好。例如,我正在尝试以下查询:

SELECT * FROM INT07NCMP
WHERE INT07_CENTRO = '7100'
AND INT07_CORRELATIVO > 0

这就是答案:

Plan hash value: 2810525850

----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |  9770 |  1450K|     1   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| INT07NCMP      |  9770 |  1450K|     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | INT07NCMP_IDX1 |    39 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

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

   1 - filter("INT07_CORRELATIVO">0)
   2 - access("INT07_CENTRO"='7100')

Note
-----
   - dynamic sampling used for this statement (level=2)

因此,如您所见,仅使用了IDX1,并且我希望使用IDX3,因为我先过滤了“ INT07_CENTRO”,然后又过滤了“ INT07_CORRELATIVO”,就像索引定义的顺序一样。如果我尝试放置更多过滤器(IDX3的所有列),则也不起作用。

对此有任何提示吗?

谢谢

1 个答案:

答案 0 :(得分:2)

假设您的统计数据不错。用户表和用户索引中的行数。

考虑到这些情况,最好的方法是简单地相信db正在做出正确的决定。它考虑了很多方面,例如统计物理组织等。因此,根据索引创建索引,并根据数据规则创建查询,然后信任数据库。

在极少数情况下,您可能必须强制执行查询。您可以使用提示。但是在这种情况下,除非它产生巨大的差异,否则我怀疑-仅在第一个索引的末尾添加relatedoivo就可以了。因为节省不是来自于此的范围扫描,而是该Oracle不必进入数据库表即可获取该信息,并且索引扫描就足够了