首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >oracle复合索引列位置和非复合索引

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

Stack Overflow用户
提问于 2014-02-21 05:33:39
回答 2查看 986关注 0票数 0

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

问题:

  1. 为了提高性能,复合键也应该包含customer_id列吗? 例如:复合键包含(列位置1处的occupation_type和列位置2中的customer_id )。这个有用吗?customer_id已经作为主键的一部分进行了索引。
  2. 在哪个列位置包括customer_id,首先还是最后,这样做的基础是什么?假设复合键包含3列,那么customer_id列应该位于哪个位置?
  3. 如果查询只包含一个列的where子句,而该列位于复合索引的第3列,则会发生什么情况?那么,综合指数有用吗?
  4. 如果该场景要运行查询(没有特定的顺序),那么索引是独立构建的还是以复合方式构建的。在下面的场景中,哪一个是有帮助的?

Query1:where tableA.columnA = value

Query2:where tableA.columnB = value

Query3:where tableA.columnC = value

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-21 10:17:43

这是我为你的案子做的数据设置。

代码语言:javascript
复制
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",我们不能提供任何意见。但一般来说,对于一个综合索引,它总是存储,按键顺序排序。当您选择某个作为任何索引( NULL)一部分的内容时,在这种情况下,将使用FAST FULL SCAN

代码语言:javascript
复制
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子句包含索引列,则进行索引范围扫描

代码语言:javascript
复制
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)

让我创建一个综合索引

代码语言:javascript
复制
CREATE INDEX IDX_TEST_1 ON TESTING(COLUMN2, COLUMN3);
CREATE INDEX IDX_TEST_2 ON TESTING(COLUMN1, COLUMN2);

除非在谓词中使用它们,否则不会产生任何影响。因此,上述语句不会在索引之后更改计划。

代码语言:javascript
复制
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说过一次

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

在快速全扫描中,我们只读取磁盘上存在的整个结构。我们不把它当作一个索引,而更像一个表。我们按顺序读取它(数据不会从索引ff中返回),我们使用多块IO读取它。

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

我们可以:

范围扫描和索引(上升或下降)组合索引(我们使用位映射索引来处理复杂和/或条件)连接索引(使用两个或多个索引连接在一起),如上面所示。

您应该始终对如何检索数据的表进行索引。

Q3 : A3

代码语言:javascript
复制
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来说,拥有单个的总是比拥有一个复合的更好。

票数 2
EN

Stack Overflow用户

发布于 2014-02-21 05:51:16

  1. 具有最多不同值的列应该放在第一位。也就是说,如果OCCUPATION_TYPE的值小于CUSTOMER_ID,则计划查询 其中CUSTOMER_ID =X和OCCUPATION_TYPE =Y 然后使用CUSTOMER_ID和OCCUPATION_TYPE创建复合索引。
  2. 请参见上面的。如果它将包含在查询中,它可能是第一位的。
  3. 可能是这样,但优化器必须评估执行索引跳过扫描,然后检索实际数据是否比全表扫描更快。
  4. 根据您的示例查询,我不明白为什么要对几个单列索引进行复合。

编辑:固定编号。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21926079

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档