You are on page 1of 10

CASE STUDY ON ORACLE STATISTIC GATHERING

Document Title : Case study on Oracle statistic gathering

Your full name

: SURESH RATNAJI

Your employer's name : WIPRO INFOTECH Your email address : suresh.ratnaji@wipro.com

Your MetaLink user id : suresh.ratnaji@wipro.com

1. PURPOSE
This script is an automated way to deal with stale statistics operations that are required to be done as part DBA activity or time of manual upgrade. Operations of this script: This script will be primarily used during database upgrade before starting the actual upgrade. Execution of this script will report stale statistics if any. It reports on schemas which are part of DBA_REGISTRY as these are the ones which are upgraded. If it finds any stale statistics it will give the recommended commands to remove those stale statistics.

2. SCENARIO
Stale data is one, in which an object in the cache is not the most recent version committed to the data source. Oracle gathers statistics on all database objects automatically and maintains those statistics in a regularly-scheduled maintenance job. Statistics can get stale during the day because of frequent DML modifications. If there are stale statistics in the database there will be chances of getting poor execution plans.

When we are gathering statistic for all objects of particular schema or complete database, Oracle build new execution plan for the entire Database object which makes the database to perform slow.

3. SOFTWARE REQUIREMENTS/PREREQUISITES
The Script needs to be run in SQL*Plus as SYS user to find the schema with stale statistics.

4. SOLUTION
To solve the issue instead of gathering complete database statistics we are gathering statistics of the culprit tables only in a schema. So, there will be less or no performance issue. Step 1: Connect as a SYS in the database and check the DB status SQL> select name,open_mode from v$database; NAME OPEN_MODE --------- ---------ORCL READ WRITE 1 row selected.

Step 2: Create a table for storing the stale object in the schema in SCOTT schema. If SCOTT schema does not exists in database you can create the table in other schema also. But change the SCHEMA NAME.STALE_OBJECT in the SHOW_STALE_OBJECT_PROC.sql table. Run the below script. REATE TABLE STALE_OBJECT ( OWNER VARCHAR2(30 BYTE),

OBJECT_NAME VARCHAR2(128 BYTE), OBJECT_TYPE VARCHAR2(18 BYTE), STATUS VARCHAR2(7 BYTE), VARCHAR2(1 BYTE)

TEMPORARY )

TABLESPACE TOOLS PCTUSED PCTFREE 40 10

INITRANS 1 MAXTRANS 255 STORAGE ( 64K 1 2147483645 0 1

INITIAL

MINEXTENTS MAXEXTENTS PCTINCREASE FREELISTS

FREELIST GROUPS 1 BUFFER_POOL ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL NOMONITORING; DEFAULT

SQL> conn scott/tiger Connected. SQL> @c:\stale_object_tbl.sql Table created.

Step 3: Create a procedure to store stale object of a schema from SYS. Modify the schema name inside according to require schema for which you need to find the stale object statistics. Here we are using it on HR user (example schema in Oracle

database) REATE OR REPLACE PROCEDURE SHOW_STALE_OBJ AS -- VARIABLES DECLARED P_OTAB DBMS_STATS.OBJECTTAB; MCOUNT NUMBER := 0; P_VERSION VARCHAR2(10); -- CURSOR DEFINED CURSOR C1 IS SELECT USERNAME SCHEMA FROM SYS.DBA_USERS WHERE USERNAME='HR';

-- BEGINNING OF THE ANONYMOUS BLOCK BEGIN

-- VERIFYING VERSION FROM V$INSTANCE --SELECT VERSION INTO P_VERSION FROM V$INSTANCE; DBMS_OUTPUT.PUT_LINE(CHR(13)); -- DEFINING LOOP 1 FOR LISTING SCHEMA WHICH HAVE STALE STATS FOR X IN C1 LOOP

DBMS_STATS.GATHER_SCHEMA_STATS(OWNNAME=>X.SCHEMA,OPTIONS=>'LIST AUTO',OBJLIST=>P_OTAB);

-- DEFINING LOOP 2 TO FIND NUMBER OF OBJECTS CONTAINING STALE STATS FOR I IN 1 .. P_OTAB.COUNT LOOP IF P_OTAB(I).OBJNAME NOT LIKE 'SYS_%' AND P_OTAB(I).OBJNAME NOT IN ('CLU$','COL_USAGE$','FET$','INDPART$',

'MON_MODS$','TABPART$','HISTGRM$',

'MON_MODS_ALL$',

'HIST_HEAD$','IN $','TAB$',

'WRI$_OPTSTAT_OPR','PUIU$DATA',

'XDB$NLOCKS_CHILD_NAME_IDX',

'XDB$NLOCKS_PARENT_OID_IDX',

'XDB$NLOCKS_RAW OKEN_IDX', 'XDB$SCHEMA_URL',

'XDBHI_IDX', 'XDB_PK_H_LINK') THEN -- INCREMENTING COUNT FOR EACH OBJECT FOUND WITH STATLE STATS MCOUNT := MCOUNT + 1; INSERT INTO SCOTT.STALE_OBJECT(OWNER, OBJECT_NAME, OBJECT_TYPE) VALUES(X.SCHEMA, P_OTAB(I).OBJNAME, P_OTAB(I).OBJTYPE); END IF; -- END OF LOOP 2

END LOOP; COMMIT;

-- DISPLAYS NO STALE STATISTICS, IF COUN IS 0 -- DISPLAYS SCHEMA WITH STALE STATS IF COUNT IS GREATER THAN 0 -IF MCOUNT !=0 THEN

DBMS_OUTPUT.PUT_LINE('------------------------------------------------------------------------------------------------------'); DBMS_OUTPUT.PUT_LINE('-- '|| X.SCHEMA || ' schema contains '|| MCOUNT || ' stale statistics use the following to gather the statistics '||'--');

DBMS_OUTPUT.PUT_LINE('------------------------------------------------------------------------------------------------------'); -DBMS_OUTPUT.PUT_LINE('|');

-- DISPLAYS COMMAND TO BE EXECUTED IF SCHEMA WITH STALE STATISTICS IS FOUND DEPENDING ON THE VERSION. ----IF SUBSTR(P_VERSION,1,5) IN ('8.1.7','9.0.1','9.2.0') THEN DBMS_OUTPUT.PUT_LINE(CHR(13)); DBMS_OUTPUT.PUT_LINE('EXEC

DBMS_STATS.GATHER_SCHEMA_STATS('''|| X.SCHEMA||''',OPTIONS=>'''||'GATHER'||''', ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE, METHOD_OPT => '''||'FOR ALL COLUMNS SIZE AUTO'||''', CASCADE => TRUE);'); -ELSIF SUBSTR(P_VERSION,1,6) IN ('10.1.0','10.2.0','11.1.0')

----

THEN DBMS_OUTPUT.PUT_LINE(CHR(13)); DBMS_OUTPUT.PUT_LINE('EXEC

DBMS_STATS.GATHER_DICTIONARY_STATS('''|| X.SCHEMA||''',OPTIONS=>'''||'GATHER'||''', ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE, METHOD_OPT => '''||'FOR ALL COLUMNS SIZE AUTO'||''', CASCADE => TRUE);'); ------END IF; ELSE DBMS_OUTPUT.PUT_LINE('-- There are no stale ELSE DBMS_OUTPUT.PUT_LINE(CHR(13)); DBMS_OUTPUT.PUT_LINE('Version is '||P_VERSION);

statistics in '|| X.SCHEMA || ' schema.'); --END IF; DBMS_OUTPUT.PUT_LINE(CHR(13));

-- RESET COUNT TO 0. MCOUNT := 0; -- END OF LOOP 1 END LOOP; END SHOW_STALE_OBJ; / SQL> conn sys as sysdba Enter password: Connected. SQL> show user USER is "SYS" SQL> @c:\SHOW_STALE_OBJECT_PROC.sql Procedure created.

Step 4: Run the procedure. SQL> EXECUTE SHOW_STALE_OBJ PL/SQL procedure successfully completed.

Step 5: Check the STALE_OBJECT table for any stale object. It will return rows if there is stale object in the schema. SQL> SQL> select a.OBJECT_NAME,a.OBJECT_TYPE,b.table_name from scott.STALE_OBJECT a,dba_indexes b where a.OWNER='HR'and a.object_name=b.index_name; OBJECT_NAME table_name OBJECT_TYPE ------------------------- ------------DEPT_ID_PK DEPARTMENTS DEPT_LOCATION_IX DEPARTMENTS EMP_DEPARTMENT_IX EMPLOYEES EMP_EMAIL_UK EMPLOYEES EMP_EMP_ID_PK EMPLOYEES EMP_JOB_IX EMPLOYEES EMP_MANAGER_IX EMPLOYEES EMP_NAME_IX EMPLOYEES JHIST_DEPARTMENT_IX JOB_HISTORY JHIST_EMPLOYEE_IX JOB_HISTORY JHIST_EMP_ID_ST_DATE_PK JOB_HISTORY JHIST_JOB_IX JOB_HISTORY JOB_ID_PK JOBS LOC_CITY_IX LOCATIONS LOC_COUNTRY_IX LOCATIONS LOC_ID_PK LOCATIONS LOC_STATE_PROVINCE_IX LOCATIONS REG_ID_PK REGIONS 18 rows selected.

INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX

Step 6: Once you found stale object in the schema, rebuild the statistics for those stale objects only instead of rebuilding for the entire object in the schema. Gather stats for the table including index SQL> exec dbms_stats.gather_table_stats('HR','EMPLOYEES',cascade=>true,d egree=>4 ,estimate_percent=>20) PL/SQL procedure successfully completed Step 7: Truncate the table.

SQL> truncate table scott.STALE_OBJECT; Table truncated. Step 8: Run the procedure again. SQL> EXECUTE SHOW_STALE_OBJ PL/SQL procedure successfully completed.

Step 9: Check the STALE_OBJECT table for any stale object. It will return rows of other table objects except employee. It wont return any stale object from employee table. SQL> select a.OBJECT_NAME,a.OBJECT_TYPE from scott.STALE_OBJECT a,dba_indexes b where a.OWNER='HR'and b.table_name='EMPLOYEES' and a.object_name=b.index_name; no rows selected

Other stale object in HR SQL> select a.OBJECT_NAME,b.table_name,a.OBJECT_TYPE from scott.STALE_OBJECT a,d ba_indexes b where a.OWNER='HR'and a.object_name=b.index_name; OBJECT_NAME -------------------------DEPT_ID_PK DEPT_LOCATION_IX JHIST_DEPARTMENT_IX JHIST_EMPLOYEE_IX JHIST_EMP_ID_ST_DATE_PK JHIST_JOB_IX JOB_ID_PK LOC_CITY_IX LOC_COUNTRY_IX LOC_ID_PK LOC_STATE_PROVINCE_IX REG_ID_PK 12 rows selected. Do the same activity from step 6 to eliminate stale object from the HR schema. TABLE_NAME -----------------------------DEPARTMENTS DEPARTMENTS JOB_HISTORY JOB_HISTORY JOB_HISTORY JOB_HISTORY JOBS LOCATIONS LOCATIONS LOCATIONS LOCATIONS REGIONS OBJECT_TYPE -----------INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX INDEX

5. REFERENCES AND LINKS


1 https://metalink.oracle.com doc id: Note:560336.1

You might also like