我有一个潜在最多5.000.000行的表。此表中的一个列在查询中单独使用,但此列只有5个可能的值,目前我有10.000行,根据解释计划,在该列上使用我的索引是没有意义的。
它会不会,或者我不应该为索引而烦恼
编辑:这是目前的两个解释计划 Without index http://img706.imageshack.us/img706/1903/noindex.png 与 With forced index via hints http://img692.imageshack.us/img692/8205/indexp.png 后一个图像我用一个提示强制使用索引。
答案 0 :(得分:8)
这取决于几件事。
首先,价值观的分配。如果您只有五个不同的值,但其中一个占表中行的99.9999%,那么显然您不希望优化器使用该值的索引,但可能希望它使用它为了其他人。在某些情况下,使用基于函数的索引是值得的,以确保您只索引感兴趣的值而不是仅占用空间的值。
其次,是否可以使用该索引回答查询而无需访问该表?
请注意,重要的不仅仅是要访问的行的百分比,而是需要访问的表的块数。例如,如果平均每个块有一个包含1000个块和30个行的表,并且一个列有30个不同的值(每个值在1000行中存在),那么需要访问的块数才能读取每一行单个值在1000/30 = 34(值得使用索引)和1000(不值得使用索引)之间变化,具体取决于行的分布方式。这是由索引的聚类因子表示的 - 如果它的值接近表中的行数,则索引不太可能被使用,如果它接近于块的数量,那么它更可能是用过的。
另外,您可以查看索引压缩以查看是否可以节省空间。
小心使用位图索引 - 它们对于多个会话同时修改的系统不友好(例如,两个人同时将行插入索引表中)。
如果您希望通过这五个值的谓词来提高查询效率,那么更有效的策略是使用分区,部分原因是查询中的分区修剪,但也因为优化器可用的统计数据有所改进知道只能访问一个分区,并且可以使用分区级统计信息而不是全局统计信息。
答案 1 :(得分:2)
索引在以下情况下非常有用:
搜索不常见的FREQUENCYID
时。例如,只有10
行的10,000,000
行FREQUENCYID = 1
并且您会搜索它。
如果在查询中不使用除FREQUENCYID
之外的其他列。这个查询:
SELECT FREQUENCYID, COUNT(*)
FROM mytable
GROUP BY
FREQUENCYID
将从索引中受益(实际上,最有可能会使用INDEX FAST FULL SCAN
和HASH AGGREGATE
)
当您的表行很大并且您在查询中使用的所有列都被编入索引时。这样,所有索引都将加入而不是FULL TABLE SCAN
。比如说,这个查询:
SELECT FREQUENCYID, OTHERCOLUMN
FROM mytable
WHERE FREQUENCYID = 2
可以通过加入FREQUENCYID
上OTHERCOLUMN
和ROWID
上的索引中的值来执行。
答案 2 :(得分:1)
如果你提到
那么它的大小会增加最多5.000.000行
我建议创建一个索引。
答案 3 :(得分:1)
可能是最简单的方法,不要猜测,但实际上是尝试。
但在我看来,您正在比较执行计划,以便找到最佳方法。这不可靠。优化程序可能没有适当的信息来选择最佳计划(例如,如果您的值分布不均匀且没有直方图)。在解释计划中查看“成本”也没有意义。
更好的方法是比较逻辑IO。运行SQL * Plus,比如set autotrace traceonly
,然后运行您的查询(有和没有索引)并比较“一致获取”数字。越少越好。
关于LIO的重要性:article by Cary Millsap。
答案 4 :(得分:0)
使用典型查询进行测试,看看哪种方式更快。</ p>
您可能会发现全表扫描的平均速度比Rowid的索引范围扫描+表访问速度快 - 在这种情况下,甲骨文做得恰到好处。
另一方面,也许存在数据模式,对于大多数查询,最好使用索引 - 在这种情况下,您可能希望添加INDEX提示。