oracle复合索引列位置和非复合索引

时间:2014-02-21 05:33:39

标签: oracle indexing

客户表包含950万条记录。 customer_id列是主键。数据库是oracle。

问题:

  1. 要提高效果,复合键是否也包含customer_id列? 例如:复合键包含列位置1中的occupation_type和列位置2中的customer_id。这有用吗? customer_id已作为主键的一部分编入索引。

  2. customer_id的哪个列位置包括,第一个或最后一个,这样做的依据是什么?假设复合键包含3列,customer_id列应该在哪个位置?

  3. 如果查询包含仅适用于复合索引的第3列的列的where子句,会发生什么?那么复合指数是否有用?

  4. 如果方案是运行诸如(没有特定顺序)的查询,那么索引应该是独立构建还是以复合方式构建。哪个在下面的场景中有用?

  5. 查询1:where tableA.columnA = value
    问题2:where tableA.columnB = value
    问题3:where tableA.columnC = value

2 个答案:

答案 0 :(得分:2)

这是我为您的案例设置的数据设置。

CREATE TABLE TESTING
(
   COLUMN1   NUMBER ( 10 ) PRIMARY KEY,
   COLUMN2   CHAR ( 12 ),
   COLUMN3   VARCHAR2 ( 12 ),
   COLUMN4   VARCHAR2 ( 12 ),
   COLUMN5   VARCHAR2 ( 12 )
);

INSERT INTO TESTING
   (SELECT ROWNUM,
           DBMS_RANDOM.STRING ( 'U', 5 ),
           DBMS_RANDOM.STRING ( 'U', 10 ),
           DBMS_RANDOM.STRING ( 'L', 10 ),
           DBMS_RANDOM.STRING ( 'L', 10 )
    FROM   ALL_OBJECTS
    WHERE  ROWNUM <= 50000 );

Q1:A1 完全取决于你想要的。既然你提到过。 "To improve performance",我们无法提供任何意见。但通常对于复合索引,它始终存储,按键顺序排序。当你选择某个属于任何索引(NOT NULL)的东西时,那么在这种情况下,使用FAST FULL SCAN

SET AUTOTRACE ON

SELECT  COUNT(DISTINCT COLUMN1) FROM TESTING;

EXECUTION PLAN
----------------------------------------------------------
   0       SELECT STATEMENT OPTIMIZER MODE=ALL_ROWS (COST=29 CARD=1 BYTES=13)
   1    0    SORT AGGREGATE (CARD=1 BYTES=13)
   2    1      VIEW SYS.VW_DAG_0 (COST=29 CARD=40 K BYTES=517 K)
   3    2        HASH GROUP BY (COST=29 CARD=40 K BYTES=517 K)
   4    3          INDEX FAST FULL SCAN SYS_C0016669 (COST=27 CARD=40 K BYTES=517 K)

如果where子句包含索引列,则会发生索引范围扫描

SET AUTOTRACE ON

SELECT  COUNT(DISTINCT COLUMN1) FROM TESTING WHERE COLUMN1 < 10;

EXECUTION PLAN
----------------------------------------------------------
   0       SELECT STATEMENT OPTIMIZER MODE=ALL_ROWS (COST=2 CARD=1 BYTES=13)
   1    0    SORT AGGREGATE (CARD=1 BYTES=13)
   2    1      VIEW SYS.VW_DAG_0 (COST=2 CARD=5 BYTES=65)
   3    2        SORT GROUP BY NOSORT (COST=2 CARD=5 BYTES=65)
   4    3          INDEX RANGE SCAN SYS_C0016669 (COST=2 CARD=5 BYTES=65)

让我创建一个复合索引

CREATE INDEX IDX_TEST_1 ON TESTING(COLUMN2, COLUMN3);
CREATE INDEX IDX_TEST_2 ON TESTING(COLUMN1, COLUMN2);

除非您在谓词中使用它们,否则这没有任何影响。因此上述声明不会在索引

之后改变计划
SET AUTOTRACE ON

SELECT  COUNT(DISTINCT COLUMN1) FROM TESTING WHERE COLUMN1 < 10;


EXECUTION PLAN
----------------------------------------------------------
   0       SELECT STATEMENT OPTIMIZER MODE=ALL_ROWS (COST=2 CARD=1 BYTES=13)
   1    0    SORT AGGREGATE (CARD=1 BYTES=13)
   2    1      VIEW SYS.VW_DAG_0 (COST=2 CARD=5 BYTES=65)
   3    2        SORT GROUP BY NOSORT (COST=2 CARD=5 BYTES=65)
   4    3          INDEX RANGE SCAN SYS_C0016669 (COST=2 CARD=5 BYTES=65)

Q2:A2 。如果CUSTOMER_ID将在where子句中频繁使用另一列,那么在这种情况下,请转到复合索引。其中的第一列应该是已排序的列。所以在你的情况下它应该是索引

的那个

(x,y)上的索引具有低聚类因子。 (假设数据按x排序)(y,x)上的索引将具有较高的聚类因子(假设数据未按y排序)

AskTom said once

INDEX_FFS(索引快速全扫描)是一个过程,我们通过读取索引数据就好像它是一个表一样。通常,索引一次处理一个块。转到根块,使用分支块进行导航。这是一种数据结构。

在FAST FULL SCAN中,我们只读取磁盘上存在的整个结构。我们不把它当作索引,而更像是一张表。我们不按顺序读取它(数据不会从索引ffs中返回),我们使用多块IO读取它。

这允许我们使用像表格的“skinnier”版本的索引。

我们可以:

范围扫描和索引(升序或降序) 组合索引(我们用位映射索引处理复杂的AND / OR条件)连接索引(使用两个或多个连接在一起的索引) 全扫描索引如上所述。

您应始终为表格索引有关检索数据的方法。

问题3:A3

SET AUTOTRACE ON
SELECT  COUNT(DISTINCT COLUMN1) FROM TESTING WHERE COLUMN3 = 'ASASDFF';

EXECUTION PLAN
----------------------------------------------------------
   0       SELECT STATEMENT OPTIMIZER MODE=ALL_ROWS (COST=138 CARD=1 BYTES=13)
   1    0    SORT AGGREGATE (CARD=1 BYTES=13)
   2    1      VIEW SYS.VW_DAG_0 (COST=138 CARD=5 BYTES=65)
   3    2        HASH GROUP BY (COST=138 CARD=5 BYTES=105)
   4    3          TABLE ACCESS FULL TESTING (COST=137 CARD=5 BYTES=105)

虽然我们有一个包含COLUMN3的复合索引,但它没用了

因此,对于 Q4:A4 ,拥有单个的总是比拥有复合的更好

答案 1 :(得分:0)

  1. 具有最大数量的不同值的列应该首先出现。也就是说,如果OCCUPATION_TYPE的值不同于CUSTOMER_ID,并且您打算查询

    WHERE CUSTOMER_ID = X AND OCCUPATION_TYPE = Y
    

    然后首先创建CUSTOMER_ID的复合索引,然后创建OCCUPATION_TYPE秒。

  2. 见上文。如果将它包含在查询中,它应该是第一个。

  3. 可能是,但优化器必须评估是否进行索引跳过扫描然后检索实际数据的速度是否比全表扫描更快。

  4. 根据您的示例查询,我不明白为什么要使用复合多个单列索引。

  5. 编辑:固定编号。