简体   繁体   中英

Join Performance Issue in Oracle

We have are having 2 tables.

  1. Table - XYZ - > Having over 189 M Records
  2. Table - ABC - > Having only 1098 records.

Our join query is some what like

select a.a, a.b, a.c 
from xyz a , ABC r 
where a.d = r.d
    and a.sub not like '0%' 
    and ((a.eff_dat < sysdate) or (a.eff_date is null))

This is how our query is performing. In any way can it be optmised to perform faster. Apart from the not like, can you suggest me any other method.

In the explain plan I have seen that it is taking the 189 M as itrator and checking with the 1098 records which is taking more time. I swapped the tables after the from Key word but also it did not work. Tried leading hint, which also not servered the purpose. Also ad column is an indexed one which is also used in the hint.

Please do suggest any methods for optimisation.

When you have multiple predicates on a table such as:

    a.sub not like '0%' 
and ((a.eff_dat < sysdate) or (a.eff_date is null))

... it is rather unlikely that the optimiser will accurately estimate the cardinality of the result set unless you use dynamic sampling, so check the explain plan to see whether:

  1. Dynamic sampling is being invoked.
  2. The estimation of the cardinalities are correct.

If the predicates are not very selective -- if they do not eliminate something in the order of 90% or the rows in the table -- then it is unlikely that an index will be of help in finding the rows, and a full scan (with partition pruning if the table is partitioned in a way that supports that) is likely to be the best access path.

I'd be reasonably sure that if there is a foreign key between the tables (ie. that all values of ad exist in rd) then the best access path is going to be a full scan of XYZ with a hash join to ABC. By the way, you mention hints but do not include them in the question. It's also unhelpful to hide the purpose of the tables with fake names, as the names often give valuable clues about the type of data and distribution of values within the data sets.

It would seem most of the cost would be in the (presumed) full table scan on the large table. I would suggest rewriting your WHERE condition as follows:

SELECT * FROM XYZ A
WHERE SUBSTR(A.SUB, 1, 1) <> '0'
AND NVL(A.EFF_DAT, TO_DATE('01-01-0001', 'MM-DD-YYYY')) < SYSDATE ;

And then create a function index that includes all the relevant columns:

CREATE INDEX IX_XYZ1 ON
XYZ(NVL(EFF_DAT, TO_DATE('01-01-0001', 'MM-DD-YYYY')), SUB, D);

Make sure the new index is being picked up by the cost-based optimizer, by checking the execution plan.

LIKE, NOT LIKE and the OR operand are some of the worst things you can use in a WHERE condition.

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