我使用的是Oracle 12c。
考虑一个表名称GRID_CELLS,它存储100,000 x 100,000网格单元数据。列如下:
索引由(X,Y)组成,它是主键。
由于它是网格单元格数据,几乎所有的单元格都是如此。有记录。
如果查询是这样的:
select * from GRID_CELLS where X >= 100 and X <= 200 and Y >= 100 and Y <= 200
Oracle将选择索引范围扫描,并将按如下方式执行:
也就是说,Oracle读取叶子节点大约100,000 * 100条记录,这比下面的(假设的)动作慢很多。
Oracle可以这样做吗?如果是这样,怎么可能被迫这样做呢?还是有其他最佳解决方案吗?
BTW,我们不能使用分区。因此,分区不是解决方案。更新
我根据下面的评论测试了2位图索引配置。结果是积极的。它比B树索引范围扫描快5~10倍。
但是,如果Oracle在范围扫描B树索引时跳过叶节点,那么它仍然会很好。
答案 0 :(得分:0)
位图索引是一种可行的方法。当使用位图索引时,甚至星形变换也是最佳的。位图索引的问题在于,当X和Y有许多不同的值时,它们很大且查询速度较慢。当表中存在的不同X和Y值的总数小于行数时,它们是最佳的。 / p>
还有一些其他步骤可以加快查询速度:
您可以按X或Y或两者对表进行分区。在这种情况下,速度增益取决于X和Y值的分布以及您的查询是否选择了一系列值。
您可以在X和Y上创建功能索引,或者将X和Y连接成一个字符串,然后在该字符串上创建索引。那你就只有一把钥匙。这可能是最好的解决方案,因为它可以将执行复杂度降低一度。
如果执行期间的磁盘I / O很高,那么将此表转换为IOT(索引组织表)将为您带来好处,但对于包含许多列的表通常就是这种情况。
在决定索引策略时,您必须始终牢记此表在生产环境中的读/写比率。如果存在高读取计数(SELECT)和低写入计数(INSERT),则需要将大部分处理写入部分:对表进行分区,创建功能索引等。如果存在高写入次数和低读取次数以及SELECT速度并不是那么重要,那么X和Y上的一个索引是最好的解决方案。