// Oracle Version 11.2.0.4 Standard Edition
// OS RedHat
I am trying to create a function index on a large table, based on using an XML object.
So I have done stuff such as:
CREATE INDEX test_function_itemgroup_id
ON test_function
(
extractValue
(
RECORD,
'/Product/PublishingDetail/ItemGroup/ItemGroupId',
'xmlns="http://www.editeur.org/onix/3.0/reference"'
)
)
So when I have a query such as:
select PRODUCT_ID
from TEST_FUNCTION pr
where
extractValue
(
RECORD,
'/Product/PublishingDetail/ItemGroup/ItemGroupId',
'xmlns="http://www.editeur.org/onix/3.0/reference"'
) = 'NAME-CLASS'
The function Index is used and I know I have the right namespace for the xml.
When I do stuff such as:
CREATE INDEX test_function_nbd
ON test_function
(
extractValue
(
RECORD,
'/Product/Extras[ExtrasIDType="RECORDCREATEDBY"]/IDValue',
'xmlns="http://www.editeur.org/onix/3.0/reference"'
)
)
select PRODUCT_ID
from TEST_FUNCTION pr
where
extractValue
(
RECORD,
'/Product/Extras[ExtrasIDType="RECORDCREATEDBY"]/IDValue',
'xmlns="http://www.editeur.org/onix/3.0/reference"'
) = 'Other'
The system does a full table scan instead of using the function index.
I have used an XMLIndex, but the performance of that has been so slow and does not seem to allow the function based indexes to be used.
Has anyone got any suggestions about how to proceed with this?
Update:
Added the full xmlns as have enough reputation now
There are no other indexes on the table.
What appears is that the Optimizer seems to be converting the XPATH to
two different queries.
/Product/Extras/ExtrasIDType and
/Product/Extras/IDValue
which are not indexed by the function.
In my particular case I can't index these individually as these can have multiple values and function based indexes can't use multiple values.
Also if I have to use two function based indexes the system will do a full table scan. (According to oracle 11 documentation)
Best Answer
Use the
/*+ NO_XML_QUERY_REWRITE */
hint. My environment for the below is11.2.0.3.0
onLinux_x86-64
platform,Enterprise Edition
.(
PCTFREE 99
, just a simple trick to spread the table over many blocks, thus making full table scan even more costly and inefficient. 1 row/block in this case.)So I have a table with 10000 rows, with XMLType values like:
And I want to run queries like, let's say:
Create the function-based index and gather statistics:
Run the query and see what happened:
Check the plan and runtime statistics:
The database transformed the XPath expression, so the function-based index is not a valid candidate anymore, so it is a full table scan with over 10000 buffer gets.
While running the same with the above hint:
Plan and runtime statistics:
Much better.
Also notice the Cost column in the plans. The cost of the first plan was 226K, but with disabling XML rewrite, the cost of the second plan was 2. I didn't investigate this topic deeper, but it seems this is another kind of query transformation, that is not based on the cost.