Link to home
Start Free TrialLog in
Avatar of vishali_vishu
vishali_vishu

asked on

how to fix this ? -- rebuild and analyze indexes ( dbms_index_utl package )

Hai !
       I am trying to do this way:

CREATE OR REPLACE PROCEDURE index_maintainance(table_name_h VARCHAR2)
IS
   table_count_p   NUMBER := 0;
BEGIN
   
   execute immediate 'alter session set db_file_multiblock_read_count=96';

   
   SELECT COUNT (table_name)
     INTO table_count_p
     FROM user_tables
    WHERE table_name = UPPER (TRIM (table_name_h));

   IF table_count_p = 1
   THEN
      dbms_index_utl.build_table_indexes (LIST    => UPPER  (TRIM (table_name_h) ),
                                                                 just_unusable       => FALSE,
                                                                 locality            => 'ALL',
                                                                 concurrent          => TRUE,
                                                                 cont_after_err      => TRUE,
                                                                 max_slaves          => 6
                                                                );
      DBMS_STATS.gather_table_stats ('My_schema', UPPER (TRIM (table_name_h)),
                                                               estimate_percent      => 20
                                                             );
   END IF;
END;
/

This is running really long ( around 2 hrs )

what's the problem with the code ?

Avatar of Guy Hengel [angelIII / a3]
Guy Hengel [angelIII / a3]
Flag of Luxembourg image

how many rows are there on the table?
how many indexes are there on the table?
partitioned table?
Avatar of vishali_vishu
vishali_vishu

ASKER

dbms_index_utl.build_table_indexes (LIST    => UPPER  (TRIM (table_name_h) ),
                                                                 just_unusable       => FALSE,
                                                                 locality            => 'ALL',
                                                                 concurrent          => TRUE,
                                                                 cont_after_err      => TRUE,
                                                                 max_slaves          => 6
                                                                );

what does locality means ?
what does max_slaves mean ? --- parallel processes ( my guess )
Table is not partitioned....

Indexes -- 12

Rows : 12 million
on 9i database  we are using this  and it is taking 1 hr and we tried to deploy the same on 10g and this is running for 5 hrs. so i change to above code and it still runs for 2 hrs.  I am estimating the statistics even though running for 2 hrs. what could be the cause ?

CREATE OR REPLACE PROCEDURE index_maintainance(table_name_h varchar2)
   IS
col_count_p number := 0;
cur_count_p number := 0;  
BEGIN

 

select count(*) into col_count_p from all_tab_cols where table_name = upper(trim(table_name_h));
if col_count_p > 0 then  

for table_indexes in (select * from user_indexes
where lower(table_name) = lower(trim(table_name_h)))
loop


execute immediate ('alter index '|| table_indexes.index_name || ' rebuild compute statistics');

end loop;
execute immediate ('analyze table '|| table_name_h || ' compute statistics');

end if;    
   
END; -- Procedure
/
the first statment will make the "inventory" of the indexes on that table. max_slaves will define that 6 processes will be started to the table stats gathering process.

now, with 12M rows, 12 indexes, it's eventually "normal" that it takes 2 hours...
but you have to check the I/O performance (of the disks).

question: are the indexes on the same tablespace than the table itself?
angelIII:
       But the same is getting done in 1 hr on 9i server. everything is replicated on to 10g server.

same structure / same tablespace names
are the hardware specs the same on the 10g server?
I suggest that you start by getting some specialist to confirm/compare the I/O performance/parameters/settings on the 2 servers.,
or. check the oracle init settings about the buffer, SGA, PGA ... can you show, side-by-side, those relevant settings
angelIII:
             i am a developer and i don't have privilages to do.
Is there anything with the code? anything messing up
>i am a developer and i don't have privilages to do.
then this should not be your job to gather stats on tables/indexes...
get the right person to do the job instead.
Why are you rebuilding your indexes?
Will you do this on a weekly basis or just for this special occasion?
ASKER CERTIFIED SOLUTION
Avatar of schwertner
schwertner
Flag of Antarctica image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This code worked for me...

i am rebuilding the indexes in parallel.
CREATE OR REPLACE PROCEDURE index_maintainance (
   table_name_h    VARCHAR2,
   schema_name_h   VARCHAR2 default 'SYS'
)
IS
   table_count_p          NUMBER          := 0;
 
   TYPE ind_tab IS TABLE OF all_indexes.index_name%TYPE;
 
   index_table            ind_tab;
   vjob_num1              job_num_tab     := job_num_tab ();
   vjob_num2              job_num_tab     := job_num_tab ();
   job_command            VARCHAR2 (200);
   n_jobs_running_count   NUMBER;
   job_list               VARCHAR2 (2000);
   break_signal           NUMBER          := 0;
BEGIN
-- CHECK IF THE TABLE EXISTS IN THE GIVEN SCHEMA
   SELECT COUNT (table_name)
     INTO table_count_p
     FROM all_tables
    WHERE table_name = UPPER (TRIM (table_name_h))
      AND owner = UPPER (TRIM (schema_name_h));
 
-- IF TABLE EXISTS THEN DO THE INDEX MAINTAINANCE JOB ON NOT VALID INDEXES ON THE SUPPLIED TABLE
   IF table_count_p = 1
   THEN
-- COLLECT THE INDEX NAMES ON THE SUPPLIED TABLES WHOSE STATUS IS NOT VALID
      SELECT index_name
      BULK COLLECT INTO index_table
        FROM all_indexes
       WHERE table_name = UPPER (TRIM (table_name_h))
         AND owner = UPPER (TRIM (schema_name_h));
 
    
 
      -- BUILD THE BACK GROUND INDEX REBUILD JOBS
      FOR i IN index_table.FIRST .. index_table.COUNT
      LOOP
         vjob_num1.EXTEND;
         job_command := 'ALTER INDEX ' || index_table (i) || ' REBUILD';
         DBMS_OUTPUT.put_line (job_command);
         DBMS_JOB.submit (job       => vjob_num1 (i),
                          what      =>    'EXECUTE IMMEDIATE '''
                                       || job_command
                                       || ''';'
                         );
      END LOOP;
 
      -- SUBMIT THE BUILT BACK GROUND JOBS -- THEY KEEP RUNNING IN THE BACKGROUND IN PARALLEL
      COMMIT;
 
      -- KEEP WAITING TILL ALL THE SUBMITTED BACKGROUND JOBS ARE DONE.
      LOOP
         dbms_output.put_line('wait loop');
         
         SELECT COUNT (job)
           INTO n_jobs_running_count
           FROM user_jobs
          WHERE job IN (SELECT column_value
                          FROM TABLE (CAST (vjob_num1 AS job_num_tab)));
 
         IF n_jobs_running_count = 0
         THEN
            -- EXIT THE LOOP ONCE ALL THE BACK GROUND JOBS ARE DONE
            break_signal := 1;
         ELSE
            DBMS_OUTPUT.put_line ('KEEP WAITING');
            -- CHECK AFTER EVERY ONE MINUTE FOR THE BACKGROUND JOB STATUS.
            DBMS_LOCK.sleep (60);
         END IF;
 
         EXIT WHEN break_signal = 1;
      END LOOP;
 
      break_signal := 0;
 
      -- BUILD THE ANALYZE INDEXES JOBS TO BE SUBMITTED IN THE BACKGROUND
      FOR i IN index_table.FIRST .. index_table.COUNT
      LOOP
         vjob_num2.EXTEND;
         -- ESTIMATE THE STATISTICS WITH 30 PERCENT OF IT'S DATA
         job_command :=
               'ANALYZE INDEX '
            || index_table (i)
            || ' ESTIMATE STATISTICS SAMPLE 30 PERCENT';
         DBMS_OUTPUT.put_line (job_command);
         DBMS_JOB.submit (job       => vjob_num2 (i),
                          what      =>    'EXECUTE IMMEDIATE '''
                                       || job_command
                                       || ''';'
                         );
      END LOOP;
 
      -- SUBMIT THE BUILT BACKGROUND JOBS TO RUN IN PRARALLEL .
      COMMIT;
      -- ANALYZE THE TABLE IN THE MEAN WHILE. THIS IS NOT DEPENDENT ON THE ABOVE BACKGROUND JOBS.
      DBMS_STATS.gather_table_stats (ownname               => UPPER
                                                                 (TRIM
                                                                     (schema_name_h
                                                                     )
                                                                 ),
                                     tabname               => UPPER
                                                                 (TRIM
                                                                     (table_name_h
                                                                     )
                                                                 ),
                                     estimate_percent      => 30
                                    );
 
      -- KEEP WAITING TILL ALLL THE BACKGROUND JOBS ARE DONE ( ANALYZE INDEXES )
      LOOP
         dbms_output.put_line('wait loop');
         SELECT COUNT (job)
           INTO n_jobs_running_count
           FROM user_jobs
          WHERE job IN (SELECT *
                          FROM TABLE (CAST (vjob_num2 AS job_num_tab)));
 
         IF n_jobs_running_count = 0
         THEN
            break_signal := 1;
         ELSE
            DBMS_OUTPUT.put_line ('KEEP WAITING');
            -- CHECK EVERY 1 MINUTE FOR THE STATUS OF THE BACKGROUND JOBS.
            DBMS_LOCK.sleep (60);
         END IF;
 
         EXIT WHEN break_signal = 1;
      END LOOP;
   END IF;
END;
/

Open in new window