Question

I am working on Oracle 10gR2

I have a MERGE statement for a table, TBL_CUSTOMER. TBL_CUSTOMER contains a column USERNAME, which contains email addresses. The data stored in this table is case insensitive, as in, the incoming data can be in upper case, lower case or any combination of cases.

While merging the data, I have to ensure that I compare data without considering case. I have created a function bases index on USERNAME column as UPPER(USERNAME).

MERGE INTO tbl_customer t
      USING (SELECT /*+ dynamic_sampling(a 2) */  NVL(
                                                      (x.username||decode((x.cnt+x.rn-1),0,null,(x.cnt+x.rn-1))),
                                                      t1.cust_username
                                                     ) community_id
                               ,DECODE (source_system_name,'SYS1', t1.cust_firstname,t1.cust_username) display_name
                               ,t1.cust_username
                              ,t1.cust_id cust_id
                              ,t1.cust_account_no cust_account_no
                              ,t1.cust_creation_date
                              ,t1.source_system_name
                              ,t1.seq_no
                              ,nvl(t1.cust_email,'NULLEMAIL') cust_email
                              ,t1.file_name
                              ,t1.diakey
                              ,t1.sourcetupleidcustmer
                              ,DECODE (source_system_name,'SYS1','DefaultPassword',t1.cust_password) cust_password
             FROM   gtt_customer_data t1,
                    (SELECT a.username,
                            cust_id,
                            row_number() over(partition by lower(a.username) order by  seq_no) rn,
                            (SELECT count(community_id)FROM TBL_customer where regexp_like (lower(community_id) ,'^'||lower(a.username)||'[0-9]*$'))cnt
                     FROM   gtt_cust_count_name a  
                    ) x
             WHERE  t1.cust_status = 'A'
             AND    x.cust_id(+)  = t1.cust_id
             AND    nvl(t1.op_code,'X') <> 'D'
             AND    t1.cust_id is not null
             AND    cust_email is not null
            ) a
      ON    ( 
             (a.sourcetupleidcustmer = t.source_tuple_id AND a.source_system_name =t.created_by)
             OR 
             ( upper(a.cust_email) = upper(t.username) AND a.source_system_name ='SYS2' )
            )

When I check the explain plan, the function based index on USERNAME is not being used. I noticed that if I remove the OR condition, the index is used, but I cannot remove that, due to complex business logic.

How can I force that index to be used?

Was it helpful?

Solution

Oracle lets you create function-based index, in your case on upper(username). You can also try INDEX hint in the query , but I think in your case function based index is a much better solution.

BTree indexes are not normally used if the index field is an argument of a function (assuming the function in WHERE and it's not a covering index). For instance, WHERE trunc(date_field) = trunc(sysdate()) will not use index on date_field, but will use index on (trunc(date_field)).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top