0

我希望我的 Oracle 行按照我的复合主键(WORK_DATE、EMP_ID)的确切升序排序。在 SQL Server 中,创建聚集索引可以轻松神奇地解决问题。乍一看,Oracle 的 ORGANIZATION INDEX(或 IOT)似乎提供了一个可行的解决方案,但事实并非如此。

以下 DDL 说明了该问题。我已经使数据尽可能真实,特别是我有一个相当大的 VARCHAR 字段,该字段的大小因行而异(这可能会阻止 Oracle 重新排序行的存储)。

我正在寻找一种解决方案,该解决方案可以使行以查询#2 的输出的方式存储,而临时用户不必添加“ORDER BY 1, 2”。我有笨拙的用户忘记添加 ORDER BY 语句,他们CTRL+END到底部,认为他们正在获取最新的 WORK_DATE。我不想通过创建一个包含嵌入式 ORDER BY 语句的视图来解决这个问题。您能否建议对 DDL 声明进行更正?也许我需要在“ORGANIZATION INDEX”关键字之后添加额外的子句或参数?谢谢你的帮助。

CREATE TABLE EMPLOYEE_HOURS (
      WORK_DATE       DATE          NOT NULL 
    , EMP_ID          VARCHAR2(15)  NOT NULL
    , HOURS_WORKED    NUMBER(22)    NOT NULL
    , WORK_COMMENT    VARCHAR2(150) NOT NULL    
    , ROW_INSERT_DATE TIMESTAMP DEFAULT SYSTIMESTAMP
    , CONSTRAINT EMPLOYEE_HOURS_PK PRIMARY KEY (WORK_DATE, EMP_ID)
) ORGANIZATION INDEX;


/* create test data that mimics my real world data */
BEGIN
    FOR loop_id IN 1 .. 10000
    LOOP

    INSERT INTO EMPLOYEE_HOURS VALUES (
          TRUNC(SYSDATE) - TRUNC(dbms_random.value(-150, 150))
        , UPPER(dbms_random.string('A', 3)) 
                       || TRUNC(dbms_random.value(1000, 999999)) 
        , dbms_random.value(0.5, 18.5)
        , regexp_replace(SUBSTR(LOWER(dbms_random.string('A', 100))
                            , 1
                            , TRUNC(dbms_random.value(4, 100))), '(.....)', '\1 ')
        , SYSTIMESTAMP);
    COMMIT WORK; 
    END LOOP;
END;


/* compare these queries and notice that the sort order in the first query does not
   conform to the expected order of the IOT composite index (WORK_DATE, EMP_ID) */

    /* Query #1 */
SELECT * FROM EMPLOYEE_HOURS;

    /* Query #2 */
SELECT * FROM EMPLOYEE_HOURS ORDER BY 1, 2;
4

1 回答 1

1

IOT 不保证连续的行存储在连续的块中。它也不保证将按排序顺序检索行。

在 oracle 中,最接近控制行存储方式的是聚簇表。

现在,我认为您的解决方案存在一些基本问题:

  1. 您声称索引对于检索有序结果是最佳的——这并不完全正确。索引扫描需要单个 IO 访问,而全扫描可以在一个 IO 中获取多个块。因此,使用索引检索具有 10 个块的表将导致 10 个 IO,而multi_block_read_count = 32使用 FTS 和哈希排序的相同查询将需要更多 CPU 但只需要一个 IO。考虑一下。

  2. 除了执行 order by 之外,没有办法保证排序结果。您可能应该在表格顶部声明一个视图并在那里执行排序。

于 2014-01-08T07:13:03.227 回答