stale (local) index statistics on partitioned table [message #649778] |
Wed, 06 April 2016 04:05 |
|
quirks
Messages: 85 Registered: October 2014
|
Member |
|
|
Hello,
we have recently upgraded to Oracle 12c. Since then we encounter sporadically a strange mystery.
In a partitioned table the (local) index statistics of ALL partitions become stale.
The table is partitioned on a daily bases (interval). In Oracle 11c only the last inserted partition had stale index stats (which is obvious, because changes only occur in this partition). But now every now and then (every 7 to 10 days) Oarcle decides to set them all stale.
I don't know what happens neither why it happens, and I have no clue how to tackle this problem (and it is a problem because the execution plans look awful). I'm open to any suggestions how to figure out why they become stale and even better how to avoid this problem.
Cheers
Quirks
|
|
|
|
Re: stale (local) index statistics on partitioned table [message #649780 is a reply to message #649779] |
Wed, 06 April 2016 04:34 |
|
quirks
Messages: 85 Registered: October 2014
|
Member |
|
|
Good questions. I'll answer them as good as I can.
1st
I came up with this, because they are marked as stale.
2nd
I suspect, that they are not stale (besides the ones for the last partition, which was automatically created from oracle while inserting new data in a new time slice / partition). Is there a way to figure out if they are truly stale or only marked as stale?
3rd
The plans are changing, so I suspect the cause is the stale status. If I gather the stats again (which takes several hours) the plans become better again.
4th
There is an automatic (daily) gathering process setup by our DBA (I basically know nothing about this one).
Furthermore there is a gathering routine for the new daily partition (see below) which produces correct /valid stats.
Toggle Spoiler[code]CREATE OR REPLACE PROCEDURE PMDAT.ANALYZE_DWH_TABS(P_TABNAME VARCHAR2) IS
CURSOR C1 IS
SELECT
USER
FROM
DUAL
WHERE
ROWNUM = 1;
V_OWNER VARCHAR2(32) := NULL;
V_TABNAME VARCHAR2(32) := UPPER(P_TABNAME);
CURSOR C2 IS
SELECT
CASE
WHEN PARTITION_NAME IS NULL THEN
TABLE_NAME
ELSE
CASE
WHEN SUBPARTITION_NAME IS NULL THEN
PARTITION_NAME
ELSE
SUBPARTITION_NAME
END
END
ANALYZE_PARTITION
,CASE
WHEN PARTITION_NAME IS NULL THEN
'GLOBAL'
ELSE
CASE
WHEN SUBPARTITION_NAME IS NULL THEN
'PARTITION'
ELSE
'SUBPARTITION'
END
END
GRANULARITY
FROM
USER_TAB_STATISTICS
WHERE
COALESCE(STALE_STATS, 'YES') = 'YES'
AND TABLE_NAME = V_TABNAME
ORDER BY
2 DESC;
CURSOR C3 IS
SELECT
DISTINCT S.INDEX_NAME
,CASE
WHEN PARTITION_NAME IS NULL THEN
TABLE_NAME
ELSE
CASE
WHEN SUBPARTITION_NAME IS NULL THEN
PARTITION_NAME
ELSE
SUBPARTITION_NAME
END
END
ANALYZE_PARTITION
,CASE
WHEN PARTITION_NAME IS NULL THEN
'GLOBAL'
ELSE
CASE
WHEN SUBPARTITION_NAME IS NULL THEN
'PARTITION'
ELSE
'SUBPARTITION'
END
END
GRANULARITY
FROM
USER_IND_STATISTICS S
WHERE
S.STALE_STATS <> 'NO'
AND S.TABLE_NAME = V_TABNAME
order by 3 desc ;
BEGIN
FOR C1_REC IN C1 LOOP
V_OWNER := C1_REC.USER;
END LOOP;
FOR C2_REC IN C2 LOOP
IF C2_REC.GRANULARITY = 'GLOBAL' THEN
DBMS_STATS.GATHER_TABLE_STATS(
OWNNAME => V_OWNER
,TABNAME => V_TABNAME
,METHOD_OPT => 'FOR ALL INDEXED COLUMNS'
,GRANULARITY => C2_REC.GRANULARITY
,NO_INVALIDATE => FALSE
,DEGREE => 5
,CASCADE => TRUE
);
ELSE
DBMS_STATS.GATHER_TABLE_STATS(
OWNNAME => V_OWNER
,TABNAME => V_TABNAME
,PARTNAME => C2_REC.ANALYZE_PARTITION
,METHOD_OPT => 'FOR ALL INDEXED COLUMNS'
,GRANULARITY => C2_REC.GRANULARITY
,NO_INVALIDATE => FALSE
,DEGREE => 5
,CASCADE => TRUE
);
END IF;
END LOOP;
FOR C3_REC IN C3 LOOP
IF C3_REC.GRANULARITY = 'GLOBAL' THEN
DBMS_STATS.GATHER_INDEX_STATS(
OWNNAME => V_OWNER
,INDNAME => C3_REC.INDEX_NAME
,ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE
,DEGREE => 5
,GRANULARITY => C3_REC.GRANULARITY
,NO_INVALIDATE => FALSE
);
ELSE
DBMS_STATS.GATHER_INDEX_STATS(
OWNNAME => V_OWNER
,INDNAME => C3_REC.INDEX_NAME
,PARTNAME => C3_REC.ANALYZE_PARTITION
,ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE
,DEGREE => 5
,GRANULARITY => C3_REC.GRANULARITY
,NO_INVALIDATE => FALSE
);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001, SQLCODE || SQLERRM);
END;
/
[/pre] [/align]
[Updated on: Wed, 06 April 2016 04:36] Report message to a moderator
|
|
|
Re: stale (local) index statistics on partitioned table [message #649788 is a reply to message #649779] |
Wed, 06 April 2016 04:56 |
John Watson
Messages: 8964 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
Are you clear on what "stale" means? It says that Oracle has detected that (by default - you can change this) 10% of the rows in an object have been changed since the object was last analyzed. You see the figures in dba_tab_modifications. Note that this view is not updated in real time, you need to exec dbms_stats.flush_database_monitoring_info to see up to date figures. So if the stats are marked as stale, there must have been considerable amount of DML against the object.
You say that plans are changing. If the stats have not changed, the plans will not change. Unless you have adaptive features or dynamic sampling enabled. Remember that in your release, the adaptive features may have a huge impact. You could test this with
ALTER SYSTEM SET optimizer_adaptive_features=false;
ALTER SYSTEM SET optimizer_dynamic_sampling=0;
and see if the plans stabilize. I wouldn't do this for anything other than diagnosis.
|
|
|
Re: stale (local) index statistics on partitioned table [message #649797 is a reply to message #649788] |
Wed, 06 April 2016 07:26 |
|
quirks
Messages: 85 Registered: October 2014
|
Member |
|
|
Well, I'm not a DBA. All I know is what I've read / heard. My understanding of how Oracle works is more guessing than knowing. But my guesswork matches very well to the info you just gave.
Toggle SpoilerAfaik (please correct me if I'm wrong), STALE means, that Oracle thinks that the statistic of how the values are spread out over the object in focus (table / partion / index / local index) has changed so much, that it is no longer a reliable source for the oracle optimizer to base its estimations on. 10% is the default value of changes in an object that can be varied before Oracle sets the Status to stale. This percentage can be set by the DBA.
"dba_tab_modifications" shows me exact the inserts in the new partition that I would expect.
When I look at "USER_IND_STATISTICS", I find partitions marked as "stale" that are not mentioned in "dba_tab_modifications" (but that probably might be the cause because I don't dare to "exec dbms_stats.flush_database_monitoring_info").
You said John Watson wrote on Wed, 06 April 2016 04:56If the stats have not changed, the plans will not change. Does that apply even if STALE_STATS = 'YES'?
I'm not sure if I can / should ALTER SYSTEM. But I obviously can recommend it to our DBA. Our current settings are :Toggle Spoiler SELECT NAME, VALUE
FROM V$PARAMETER
WHERE NAME IN ('optimizer_adaptive_features', 'optimizer_dynamic_sampling');
NAME VALUE
optimizer_dynamic_sampling 2
optimizer_adaptive_features TRUE
I've tried to set the options you've recommended as session parameters and indeed the plans became better. While playing around I figured that "optimizer_dynamic_sampling=0;" did the trick. "optimizer_adaptive_features=false;" seems to enable / disable the dynamic sampling as well.
Now I'm a little bit confused. Is it possible that "stale" index statistics do trigger oracle to do dynamic sampling? If so, that leads me back to my first question. Why do they get stale in the first place even if there is no change (in that specific partitions)?
|
|
|
|
Re: stale (local) index statistics on partitioned table [message #649799 is a reply to message #649798] |
Wed, 06 April 2016 08:12 |
|
quirks
Messages: 85 Registered: October 2014
|
Member |
|
|
BlackSwan wrote on Wed, 06 April 2016 07:36you need to query different views for partitioned indexes as compared to "regular" indexes
For the usability of indices I've to look in the corresponding view. And I can see when it was analyzed.
For the index statistics I only know "USER_IND_STATISTICS". Can you probably give me a hint what to search for in google (I could not find any)?
[Updated on: Wed, 06 April 2016 08:19] Report message to a moderator
|
|
|