Database Reference
In-Depth Information
Consider the simple EMP and DEPT tables. EMP has a foreign key to DEPT (the DEPTNO column). The DEPT table has
the DNAME attribute (the name of the department). The end users will frequently ask questions such as “How many
people work in sales?”, “Who works in sales?”, “Can you show me the top N performing people in sales?” Note that
they do not ask, “How many people work in DEPTNO 30?” They don't use those key values; rather, they use the
human-readable department name. Therefore, they end up running queries such as the following:
select count(*)
from emp, dept
where emp.deptno = dept.deptno
and dept.dname = 'SALES'
/
select emp.*
from emp, dept
where emp.deptno = dept.deptno
and dept.dname = 'SALES'
/
Those queries almost necessarily have to access the DEPT table and the EMP table using conventional indexes.
We might use an index on DEPT.DNAME to find the SALES row(s) and retrieve the DEPTNO value for SALES , and then use
an INDEX on EMP.DEPTNO to find the matching rows; however, by using a bitmap join index we can avoid all of that.
The bitmap join index allows us to index the DEPT.DNAME column, but have that index point not at the DEPT table, but
at the EMP table. This is a pretty radical concept—to be able to index attributes from other tables—and it might change
the way to implement your data model in a reporting system. You can, in effect, have your cake and eat it, too. You can
keep your normalized data structures intact, yet get the benefits of denormalization at the same time.
Here's the index we would create for this example:
EODA@ORA12CR1> create bitmap index emp_bm_idx
2 on emp( d.dname )
3 from emp e, dept d
4 where e.deptno = d.deptno
5 /
Index created.
Note how the beginning of the CREATE INDEX looks “normal” and creates the index INDEX_NAME on the table.
But from there on, it deviates from “normal.” We see a reference to a column in the DEPT table: D.DNAME . We see a
FROM clause, making this CREATE INDEX statement resemble a query. We have a join condition between multiple
tables. This CREATE INDEX statement indexes the DEPT.DNAME column, but in the context of the EMP table. If we ask
those questions mentioned earlier, we would find the database never accesses the DEPT at all, and it need not do
so because the DNAME column now exists in the index pointing to rows in the EMP table. For purposes of illustration,
we will make the EMP and DEPT tables appear large (to avoid having the CBO think they are small and full scanning
them instead of using indexes):
EODA@ORA12CR1> begin
2 dbms_stats.set_table_stats( user, 'EMP',
3 numrows => 1000000, numblks => 300000 );
4 dbms_stats.set_table_stats( user, 'DEPT',
5 numrows => 100000, numblks => 30000 );
6 dbms_stats.delete_index_stats( user, 'EMP_BM_IDX' );
7 end;
8 /
PL/SQL procedure successfully completed.
 
Search WWH ::




Custom Search