用于范围查询条件的Oracle组合索引

时间:2012-05-04 16:43:11

标签: oracle optimization indexing composite-index

我有一张表Blah(纬度浮点数,经度浮点数,create_time日期,owner_id int,.....)

我的代码只执行一次查询

select * 
from Blah 
where latitude < l1 and latitude > l2   
and longitude < ll1 and longitude > ll2   
and create_time < t1 and create_time > t2 
and owner_id < o1 and owner_id > o2 ;

(当然值l1,l2,...... o1,o2是来自程序的动态参数)

我的问题是我应该创建什么样的索引;综合指数? 在复合索引的情况下,我应该先放哪一列? 指数的效果如何?

我想了很久,并且找不到有关oracle索引如何工作的详细文档。

我可以找到使用B-tree实现的文档,在我们的例子中:B-tree中的每个键都是一个4元组:( column1,column2,column3,column4),其中定义了这些元组的排序关系是词汇顺序。

然后对于上面的查询,假设我们的订单是(owner_id,create_time,纬度,经度),我猜 oracle首先需要二进制搜索到点(o1,t1,l1,ll1),对于这个操作,索引确实很有用。 但接下来,我们需要找到第一个interium的终点:我们需要找到(o1,t1,l1,ll2),这也可以通过二分搜索来完成。

接下来,我们需要找到满足条件的下一部分,所以我们需要 find(o1,t1,lx,ll1)其中lx是大于l1的下一个值,我们也可以通过二分查找找到它。 但在我们的情况下,很可能在同一纬度,经度不超过1, 所以这里的二分搜索并不比线性扫描更有效。

遵循这种精神,似乎我们应该首先使用小值范围基数列, 在这种情况下,create_time,如果我们的点只在几天内创建。 如果我们从不做范围条件,但只有等于(=)条件,那么哪一列是第一个并不重要,对吗?

为了更清楚,这是一个更简单的例子:

假设我有2列,X和Y

db中的

,两者的值都是[1,2,...... 100],所以我们有100x100行

我的查询是

select * from mytable where X > 34 and X < 78 and Y > 12 and Y < 15;

说我们的索引在(X,Y)上,所以2个值之间的比较规则是

v1 < v2 <=====>  v1.x < v2.x || v1.x == v2.x && v1.y < v2.y

根据上面的排序规则,我们可以看到索引中的值是 按顺序排列(x,y的值):

1,1, 1,2 1,3 .... 1,100     
2,1  2,2 2,3 ......2,100
.....
100,1 100,2 ....... 100,100

现在,要搜索查询中的值,B-Tree遍历需要 找到(78-34-1)间隔,因此(78-34-1)* 2查找(1为开头 一个用于结束位置),而不仅仅是2个查找。

因此,如果我们有更高的维度,则间隔计数会呈指数增长 随着尺寸的数量,所以索引可能不再有用------ 这是我关心的问题

非常感谢 杨

5 个答案:

答案 0 :(得分:9)

如果您的唯一目标是创建一个索引来优化此查询,那么您希望首先使用最具选择性的列对复合索引中的列进行排序。如果latitude上的谓词消除了比其他谓词多得多的行,那么首先使该列更有效。如果owner_id上的谓词消除了比其他谓词多得多的行,那么首先使该列更有效率。

但实际上,我们很少创建索引,其唯一目的是优化单个查询。通常,为了使索引维护的开销值得,我们希望索引在许多查询中都有用。在复合索引的情况下,这意味着按查询在该列上具有谓词的概率对列进行排序。例如,如果您在owner_id, create_time, latitude, longitude上有复合索引,则可以将其用于仅在owner_id上指定谓词的查询。但实际上,您不会将该索引用于仅在longitude上指定谓词的查询。

答案 1 :(得分:3)

首先,请记住“B-Tree”中的“B”不是“二元”。

其次,在Oracle中进行索引时,如果出现以下情况,您还可以选择位图索引:

  1. 您拥有企业版许可证
  2. 您没有多个会话同时修改表
  3. 您的索引值不是唯一的(位图索引仅可用于低基数列的语句通常会被夸大)
  4. 位图索引擅长的一种查询是有效地将谓词组合在多个列上,特别是在谓词列集变化的情况下(当然,情况可能并非如此)。如果您满足上述三个条件,则值得测试表上有四个独立位图索引的效果。

答案 2 :(得分:1)

一个简单的暴力解决方案是在同一个表上创建多个索引组合,在启用EXPLAIN PLAN的情况下运行查询,然后选择DBMS更喜欢使用的索引。

答案 3 :(得分:0)

此表用于OLTP还是DWH? 如果此表上没有很多单行/多线程DML语句,则可以使用位图索引。 位图索引允许您在多个索引之间使用ROWID AND运算符(Aka星变换)。为了做到这一点,在每列上创建一个位图索引。 就像我说的那样,这个解决方案最适合DWH系统,在这个系统中您只需要一个批量插入。

答案 4 :(得分:0)

在标准B树索引之外,最好处理多维范围查询,恕我直言。关于一般主题的一些论文可以通过网络搜索“多维范围查询”找到。

Oracle提供了一个名为Oracle Spatial的产品。该产品的文档在Chapter 4中包含创建空间索引和执行查询的示例和说明。没有新的SQL语法;他们创建索引的例子是:

CREATE INDEX territory_idx ON territories (territory_geom)
    INDEXTYPE IS MDSYS.SPATIAL_INDEX;

创建一个R树索引。

我认为R树,kdb树和类似空间结构的存在证明了标准B树可能不适合这些应用。