Skip to Main Content
  • Questions
  • Dynamic Query is running Slow in 12 C

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Hemant.

Asked: November 17, 2016 - 12:50 pm UTC

Last updated: November 19, 2016 - 1:58 am UTC

Version: 12C

Viewed 1000+ times

You Asked

Hi Tom,
I had 1 sql file which was running perfectly fine in 10G but after migration to 12 c performance is very poor.
The query logic is :
A table has around 550 columns and data is getting inserted into this table from XL Sheet. Once loaded then we need to check :
first, which column has value (ignoring 10-15 columns which we will be used for reference).
And if value is present then identify those columns which can be used later.

For Example, below query was working good in 10G but running very poorly in 12 C.

CURSOR C_MASTER_CLAIM IS
SELECT a.OWNER || '.' || A.TABLE_NAME, a.Column_Name
FROM all_tab_cols a
WHERE A.owner = v_owner
AND a.table_name IN (v_master_clm_tbl)
AND a.hidden_column = 'NO'
AND user_generated = 'YES'
AND A.column_name NOT IN
(REFERENCE COLUMN);
BEGIN

v_master_clm := v_owner || '.' || v_master_clm_tbl;

OPEN C_MASTER_CLAIM;
LOOP
FETCH C_MASTER_CLAIM BULK COLLECT
INTO V_MASTER_CLAIM LIMIT 1000;
FOR i IN 1 .. V_MASTER_CLAIM.count LOOP


V_EXISTS_RECORD_CLAIM := 0;

EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM '|| v_master_clm ||'
WHERE NVL(submitted, ''NO'') = ''NO''
AND NVL(action, ''X'') NOT IN (''ADJ'', ''M'')
AND state = ' || '''' ||v_state || '''' || '
AND type_of_claim = ' || '''' || v_type || '''' || '
AND TTID = ' || '''' || v_tt || '''' || '
AND '|| V_MASTER_CLAIM(J).COLUMN_NAME||' IS NOT NULL '
INTO V_EXISTS_RECORD_CLAIM;

IF V_EXISTS_RECORD_CLAIM > 0 THEN

--To mark data which have VALUES in COLUMNS and hence fetching value from different table to update in main table.

V_SQL1:= 'UPDATE '||v_master_clm||' m
SET UPDATE_LEVEL = UPDATE_LEVEL||'',''||(SELECT COLUMN_NO FROM ' || v_special_update_tbl || ' t
WHERE COLUMN_NAME = ' || '''' ||V_MASTER_CLAIM(i).COLUMN_NAME ||'''' ||'
AND t.COLUMN_IN IN (''HEADER'', ''DETAIL'')
AND t.TABLE_CATEGORY = '||''''||V_TABLE_CATEGORY ||''''||'
AND ROWNUM=1)
WHERE m.TTID = :p_tt
AND '||V_MASTER_CLAIM(i).COLUMN_NAME||' IS NOT NULL
AND (DATA_LEVEL IS NULL OR NVL(DATA_LEVEL,''EMPTY'') LIKE ''%IcnNull%'')
AND m.state = :p_state
AND m.type_of_claim = :p_type
';
EXECUTE IMMEDIATE V_SQL1
USING v_tt, v_state, v_type; -- These value will be passed as parameter

END IF;

END LOOP;
EXIT WHEN C_MASTER_CLAIM%notfound;

END LOOP;
IF C_MASTER_CLAIM%isopen THEN
CLOSE C_MASTER_CLAIM;
END IF;

END;


Please let me know your suggestions to improve performance or other way of writing logic.

and Connor said...

Firstly - you need to work out whether it is the SELECT or the UPDATE that is running slowly. I will assume the SELECT but you should confirm this.

If I asked you if you had a particular tree had any leaves, would you check for at least one leaf ? or climb the tree and count every single one ?

So change:

AND '|| V_MASTER_CLAIM(J).COLUMN_NAME||' IS NOT NULL '

to

AND '|| V_MASTER_CLAIM(J).COLUMN_NAME||' IS NOT NULL and rownum = 1'

and see if that improves things.


Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Peformance Improved

Hemant Singh, November 18, 2016 - 8:24 am UTC

Thanks Connor !! Yes performance improved but still not up to the marks.
And yes SELECT was running slow, If something wrong in my logic? And if Optimizer is deciding Explain plan for every single data ? If yes then Bind Variable can be used like :

EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM NEMIS.TT_MASTER_CLAIM WHERE TTID = :tt AND state = :state
AND type_of_claim = :type AND NVL(action, ''X'') NOT IN (''ADJ'', ''M'')
AND '||V_MASTER_CLAIM(J).COLUMN_NAME||' IS NOT NULL
AND ROWNUM = 1'
INTO V_EXISTS_RECORD_CLAIM USING v_tt, v_state,v_type;


Also there can be problem due to improper INDEXING on table as there is no INDEX on column TTID?


Connor McDonald
November 19, 2016 - 1:58 am UTC

If this is a frequent activity, you could create a custom index for this particular purpose, ie, an index on

ttid,state,type_of_claim

but obviously I dont have the required information to help you make that decision

Adding 1 more query

Hemant Singh, November 18, 2016 - 8:27 am UTC

Can we pass bind variable for '|| V_MASTER_CLAIM(J).COLUMN_NAME||' ?

While passing result was not appropriate, seems its a Identifier and hence can`t be passed like this ? Please confirm.
Connor McDonald
November 19, 2016 - 1:58 am UTC

No. Binding it for predicate *values* not for the tables/columns themselves