Superdooperhero
Superdooperhero

Reputation: 8096

Oracle compressed/b-tree index how and when to use

I would like to add a compressed index to the Oracle Applications workflow table hr.pqh_ss_transaction_history in order to access specific types of workflows (process_name) and workflows for specific people (selected_person_id).

There are lots of repeating values in process_name although the data is skewed. I would however want to access the TFG_HR_NEW_HIRE_PLACE_JSP_PRC and TFG_HR_TERMINATION_JSP_PRC process types.

"PROCESS_NAME","CNT"
"HR_GENERIC_APPROVAL_PRC",40347
"HR_PERSONAL_INFO_JSP_PRC",39284
"TFG_HR_NEW_HIRE_PLACE_JSP_PRC",18117
"TFG_HREMPSTS_TERMS_CHG_JSP_PRC",14076
"TFG_HR_TERMINATION_JSP_PRC",8764
"HR_ADV_INDIVIDUAL_COMP_PRC",4907
"TFG_HR_SIT_NOAPP",3979
"TFG_YE_TAX_PROV",2663
"HR_TERMINATION_JSP_PRC",1310
"HR_CHANGE_PAY_JSP_PRC",953
"TFG_HR_SIT_EXIT_JSP_PRC",797
"HR_SIT_JSP_PRC",630
"HR_QUALIFICATION_JSP_PRC",282
"HR_CAED_JSP_PRC",250
"TFG_HR_EMP_TERM_JSP_PRC",211
"PER_DOR_JSP_PRC",174
"HR_AWARD_JSP_PRC",101
"TFG_HR_SIT_REP_MOT",32
"TFG_HR_SIT_NEWPOS_NIB_JSP_PRC",30
"TFG_HR_SIT_NEWPOS_INBU_JSP_PRC",28
"HR_NEW_HIRE_PLACE_JSP_PRC",22
"HR_NEWHIRE_JSP_PRC",6

selected_person_id would obviously be more selective. Unfortunately there are 3774 nulls for this column and the highest count after that is 73 for one person. A lot of people would only have 1 row. The total row count is 136963.

My query would be in this format:

select psth.item_key,
       psth.creation_date,
       psth.last_update_date
from   hr.pqh_ss_transaction_history psth
where  nvl(psth.selected_person_id, :p_person_id) = :p_person_id
and    psth.process_name = 'HR_TERMINATION_JSP_PRC'
order  by psth.last_update_date

I am on Oracle 12c release 1.

I assume it would be a good idea to put a non-compressed b-tree index on selected_person_id since the values returned would fall in the less than 5% of the total rows scenario, but how do you handle the nulls in the column which would not go into the index when you select using nvl(psth.selected_person_id, :p_person_id) = :p_person_id? Is there a more efficient way to write the sql and how should you create this index?

For process_name I would like to use a compressed b-tree index. I am assuming that the statement is

CREATE INDEX idxname ON pqh_ss_transaction_history(process_name) COMPRESS 

where there would be an implicit second column for rowid. Is it safe for it to use rowid here, since normally it is not advised to use rowid? Is the skewed data an issue (most of the time I would be selecting on the high volume side)? I don't understand how compressed indexes would be efficient. For b-tree indexes you would normally want to return 5% of the data, otherwise a full table scan is actually more efficient. How does the compressed index return so many rowids and then do lookup into the full table using those rowids, faster than a full table scan?

Or since the optimizer will only be able to use one of the two indexes should I rather create an uncompressed function based index with selected_person_id and process_name concatenated?

Upvotes: 0

Views: 513

Answers (1)

Tony Andrews
Tony Andrews

Reputation: 132580

Perhaps you could create this index:

CREATE INDEX idxname ON pqh_ss_transaction_history
  (process_name, NVL(selected_person_id,-1)) COMPRESS 1

Then change your query to:

select psth.item_key,
       psth.creation_date,
       psth.last_update_date
from   hr.pqh_ss_transaction_history psth
where  nvl(psth.selected_person_id, -1) in (:p_person_id,-1)
and    psth.process_name = 'HR_TERMINATION_JSP_PRC'
order  by psth.last_update_date

Upvotes: 2

Related Questions