如果我有一个表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'
我应该创建哪些索引?使用列COL1
和COL2
创建一个会为两个查询编制索引,还是只需要COL2
的另一个索引才能让第二个查询更快?
谢谢!
答案 0 :(得分:5)
两个查询都可以使用table_a(COL2, COL1)
上的常规B树索引。
单独使用COL2
索引可能会更有效地仅使用此列上的过滤器来检索行,但附加索引将使用空间并减慢插入速度(如果更新此列,则会更新)。这是一种权衡。
答案 1 :(得分:4)
在他的回答中,文森特说:
“table_a(COL2,COL1)上的常规B树索引可以由两者使用 查询“。
该句中的关键词是“可以”。因为任何一个查询都可能不会使用这样的索引。
数据库索引是一个复杂而微妙的主题。有entire books written on the topic。 Richard Foote已成功维持a blog talking about nothing but Oracle Indexes(和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'而其余的是高度选择性的,那么索引可能有用也可能没用。我们可能需要在收集索引时生成直方图,但是当查询使用文字而不是绑定变量时,它们才真正有用。
答案 2 :(得分:1)
您可以考虑在col2和col1上使用复合索引。有关详细信息,请参阅Oracle concepts guide