位图联接索引需要主键或维列上的唯一约束条件,因为重复行会显著改变位图的工作方式。允许重复会导致数据结构效率大大降低,在极少数情况下需要大量代码更改,或者两者兼而有之。(由于我们无法访问Oracle的源代码,这个答案大多是推测,但基于位图索引的工作方式,我认为这些猜测是合理的。) 首先,下面的示例演示了如何创建和使用部分基于this Oracle-base article的简单位图连接索引。(通常很大),以及一个CUSTOMER维度表位图索引预联接这两个表,并将CUSTOMER.STATE值作为隐藏列SYS_NC00004$存储在SALES表中。位图联接索引允许联接表的查询使用位图索引,并且在运行时不访问或联接CUSTOMER表。当解释计划中的BITMAP INDEX SINGLE VALUE操作使用索引IDX_CUSTOMTER_SALES而不是CUSTOMER表时,我们可以看到这种情况。
--drop table customer;
--drop table sales;
create table sales(sales_id number primary key, dollar_amount number not null, cust_id number not null);
insert into sales values(1, 100, 1);
insert into sales values(2, 200, 2);
create table customer(cust_id number primary key, state varchar2(100) not null);
insert into customer values(1, 'CA');
insert into customer values(2, 'NY');
create bitmap index idx_customter_sales
on sales(customer.state)
from sales, customer
where sales.cust_id = customer.cust_id;
explain plan for
select /*+ index(sales idx_customter_sales) */ sum(sales.dollar_amount)
from sales,
customer
where sales.cust_id = customer.cust_id
and customer.state = 'CA';
select * from table(dbms_xplan.display);
--Plan:
Plan hash value: 477564610
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| SALES | 1 | 26 | 6 (0)| 00:00:01 |
| 3 | BITMAP CONVERSION TO ROWIDS | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE | IDX_CUSTOMTER_SALES | | | | |
------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("SALES"."SYS_NC00004$"='CA')
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
CUSTOMER.STATE bitmap for SALES ROWID AAAftAAAMAAAK0kAAA - AAAftAAAMAAAK0kZZZ
-------------- --------------------------------------------------------------
CA 10...
NY 01...
CUSTOMER.STATE count(?) map for SALES ROWID AAAftAAAMAAAK0kAAA - AAAftAAAMAAAK0kZZZ
-------------- --------------------------------------------------------------
CA 20...
NY 01...
1条答案
按热度按时间gopyfrb31#
位图联接索引需要主键或维列上的唯一约束条件,因为重复行会显著改变位图的工作方式。允许重复会导致数据结构效率大大降低,在极少数情况下需要大量代码更改,或者两者兼而有之。(由于我们无法访问Oracle的源代码,这个答案大多是推测,但基于位图索引的工作方式,我认为这些猜测是合理的。)
首先,下面的示例演示了如何创建和使用部分基于this Oracle-base article的简单位图连接索引。(通常很大),以及一个CUSTOMER维度表位图索引预联接这两个表,并将CUSTOMER.STATE值作为隐藏列SYS_NC00004$存储在SALES表中。位图联接索引允许联接表的查询使用位图索引,并且在运行时不访问或联接CUSTOMER表。当解释计划中的
BITMAP INDEX SINGLE VALUE
操作使用索引IDX_CUSTOMTER_SALES而不是CUSTOMER表时,我们可以看到这种情况。位图索引为每个不同的值创建一个新的位图。使用ROWID(物理地址),Oracle只需使用一个位就可以确定每个值是否与每个表行匹配。ROWID是内部物理结构,我们不知道它们是如何工作的,但可以肯定的是,ROWID是有序的,Oracle不必为每一行列出ROWID。索引压缩行号,可能使用一些元数据来指示“这个长的位列表用于ROWID范围AAAftAAAMAAAK 0 kAAA到AAAftAAAMAAAK 0 kZZZ”
从逻辑上讲,位图看起来像这样:
每个位图非常小,因为每个表行只需要1位加上少量开销。如果还有其他列的位图,Oracle可以将
AND
predicate 作为简单的布尔CPUAND
来执行,这是超级快的。但是,如果列不是非常唯一,并且有许多位图,那么索引将是巨大的,效率低下。添加重复的维行会破坏一切。例如,假设我们为加州添加了重复的客户:
现在,两个表之间的连接可能返回重复项--SALES中的一行可能与CUSTOMER中的多行匹配。Oracle通常可以轻松地处理这种情况,但我不确定它是否可以使用位图索引来处理这种情况。简单的0或1不再是足够的信息--数据库还需要知道有多少重复项。现在,我们存储计数而不是位,如下所示:
现在数据结构已经从位变成了字节,如果有大量重复数据,甚至可能变成多个字节,位图连接索引的大小现在至少增加了8倍,它们不能再用于快速的二进制数学运算。
允许重复消除了位图连接索引的所有优点。而且这可能是一个非常罕见的用例。我不确定在事实表和维度表之间建立一对多关系是否有意义。