0

如果我有一张桌子TABLE_1,可以说 5 列:

COL1    |   COL2    |   COL3    |   COL4    |   COL5
[line]
[line]
[...]

我想做两个主要的查询:

SELECT * FROM table_a WHERE COL1 = 'X' and COL2 = 'Y'

另一个是:

SELECT * FROM table_a WHERE COL2 = 'Z'

我应该创建哪些索引?创建一个带有列COL1COL2索引并为两个查询建立索引,或者我是否需要另一个索引COL2才能更快地进行第二个查询?

谢谢!

4

3 回答 3

5

table_a(COL2, COL1)两个查询都可以使用常规的 B 树索引。

单独使用索引COL2可能更有效地仅在此列上使用过滤器来检索行,但附加索引将占用空间并减慢插入速度(如果您更新此列,则更新速度)。这是一个权衡。

于 2011-07-29T09:22:10.487 回答
4

在他的回答中,文森特说:

“两个查询都可以使用 table_a(COL2, COL1) 上的常规 B 树索引。”

那句话中的关键词是“可以”。因为这也是事实,任何一个查询都可能不使用这样的索引。

数据库索引是一个复杂而微妙的主题。有关于这个主题的整本书多年来,Richard Foote 一直设法维护一个只讨论 Oracle 索引(和 David Bowie)的博客。

如果不了解有关表的一些基本事实,我们就无法对这个问题给出明确的答案:它有多少行?COL1 有多少个不同的值?COL2 有多少个不同的值?

所以,让我们看一些替代答案。

如果 TABLEA 仅包含十几行,则全表扫描的机会可能比任何索引读取更有效。

如果 COL2 是唯一的,我们需要的唯一索引是table_a(COL2)

如果 COL2 是非选择性的(与总行数相比值相对较少),那么第二个查询应该使用全表扫描而不是索引读取。

如果 COL2 是非选择性的,但 COL1 是高度选择性的(与总行数相比值非常多,但不是唯一的),那么第一个查询应该使用table_a(COL2, COL1).

如果 COL2 不是特别有选择性,而 COL1 不是特别有选择性,但两者的组合是高度选择性的,那么第一个查询应该使用 上的索引table_a(COL2, COL1)。全表扫描将是第二个查询的首选路径。

如果 COL1 是唯一的,它应该有一个索引,这将在第一个查询中使用,但它显然对第二个查询没有帮助。

然后是 NULL 问题,这使问题进一步复杂化。NULL 不被索引,除了复合索引(和某些其他特殊情况)。

一个真正完整的答案还可以解决倾斜问题:如果 COL1 中 90% 的行是“0”,其余的都是高度选择性的,那么索引可能有用也可能没有用。我们在收集索引时可能需要生成直方图,但只有在查询使用文字而不是绑定变量时它们才真正有用。

于 2011-07-29T16:30:41.107 回答
1

您可以考虑在 col2 和 col1 上使用复合索引。有关更多详细信息,请参阅Oracle 概念指南

于 2011-07-29T09:26:22.520 回答