简体   繁体   中英

Oracle SQL: Can the rows in a subset returned by using a non-unique index also be queried by using a second non-unique index?

Sorry if the title is confusing, I am finding it difficult to clearly word my question.

Here is my scenario: I have a table called SUBSCRIBERS that has two non-unique indexes. The columns indexed are AREA_ID and SUBSCRIPTION_DATE.

Now, I want to (efficiently) query for all subscribers in a specific area who have subscribed after a given date. Example SQL:

SELECT *
FROM subscribers
WHERE area_id = 'areaID'
AND subscription_date > to_date(some_date)

So let's say to execute this query, Oracle first grabs all the rows with given areaID, and let's say this is still a very large number of rows. Will Oracle be able to do a range scan on this subset of rows by subscription date? Or does the non-unique subscription_date index only apply to the FULL table, meaning that Oracle will have to do a linear scan over the subset?

Also, I'm not sure what the technical phrase would be to describe an index on a set that also applies to subsets. That would be a cool bonus if anyone knows the correct terminology.

Depending on the Oracle version, it is possible that both indexes could be used. However, in order to do this, Oracle would have to convert both b-tree indexes to bitmap indexes and do a bitmap merge on the two. This is not a particularly efficient operation, so it is not generally not a query plan that you'd want.

Oracle b-tree indexes work by storing the key and the ROWID in the table where the key occurs. In order to combine the indexes, Oracle first converts them to a bitmap index which is essentially a two-dimensional array that indicates which row meets which criteria. It can then combine the two bitmap indexes relatively easily. The complexity of this operation is in the initial conversion of the b-tree index into a bitmap index. In principle, nothing prevents Oracle from implementing a query plan that fetches all the ROWIDs from both indexes and perform an intersection of the two sets. I assume, however, that the bitmap conversion path is more efficient in general because that's what Oracle implemented.

Jonathan Lewis has a section on bitmap conversions in his book Cost-Based Oracle Fundamentals.

It would almost certainly be more efficient to have a composite index on ( AREA_ID , SUBSCRIPTION_DATE ). That would allow you to do an index range scan on the single composite index. Queries that just had a predicate on AREA_ID would be able to use this composite index so the index on AREA_ID would generally be made redundant.

For the sake of completeness, I wanted to post this excerpt from Markus Winand's site, which intuitively explains why more than one distinct b-tree index can't be simultaneously used by a query engine:

...a chain with one axis supports one range condition as an access predicate. Supporting two range conditions as an access predicate would mean to scan a corner of a chessboard. However, a B-Tree index is a chain—there is no second axis.

Source: http://use-the-index-luke.com/sql/where-clause/searching-for-ranges/index-merge-performance

And helpful diagrams: http://use-the-index-luke.com/sql/anatomy/the-tree

In other words, b-tree indexes only construct a sorted tree based on one data field. The nodes of the index are n-tuples, but the entries of the index are 1-tuples.

It seems like to query the subset returned by one b-tree index with a second b-tree index, the entries of the first b-tree index would need to additionally store a reference to each row's location in the second b-tree index. But then, I'm not sure if that would even work, since b-tree indexes are intended to retrieve based on value , not on location--they are not random access data structures.

Not sure at first glance what complexity this would introduce, but I'm sure it would be a nightmare with multiple indexes. You would need a mechanism to add additional index location references (each additional index would convert the entries in your index from n-tuples to (n+1)-tuples), you would need a mechanism to apply a filter on the other indexes to skip non-referenced locations, and you would need a mechanism to sync the references across indexes upon create/update/delete operations on your table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM