Вы находитесь на странице: 1из 5

Real-Time Tuning Examples:

==========================
Dumping the data in to our test schema:

conn ptuser/oracle

drop table obj purge;


drop table TAB1 purge;
drop table T1 purge;
drop table SYN purge;
drop table PROC purge;
drop table OBJ purge;

create table obj as select * from sys.dba_objects;


insert into obj select * from sys.dba_objects; -- 6 iterations
commit;

create table tab1 as select * from sys.dba_tables;


insert into tab1 select * from sys.dba_tables;
commit;

create table proc as select * from sys.dba_procedures;


insert into proc select * from sys.dba_procedures;
commit;

create table ind as select * from sys.dba_indexes;


insert into ind select * from sys.dba_indexes;
commit;

create table syn as select * from sys.dba_synonyms;


insert into syn select * from sys.dba_synonyms;
commit;
alter system flush shared_pool;
alter system flush buffer_cache;

autotrace on
explain plan..

First SQL statement:


select table_name,tablespace_name,status from tab1 where num_rows > 1000;

Checking the EXECUTION PLAN:


set head on
set autotrace TRACEONLY
PTUSER@orcl>set autotrace TRACEonly
PTUSER@orcl>select table_name,tablespace_name,status from tab1 where num_rows >
1000;

PTUSER@orcl>select count(*) from tab1;

COUNT(*)
----------
19671

-> check the index


PTUSER@orcl>select INDEX_NAME,TABLE_OWNER,TABLE_NAME from USER_INDEXES where
TABLE_NAME='TAB1';

no rows selected

PTUSER@orcl>

-> Create index


create index tab1_num_rows_ind on tab1(num_rows);

alter system flush shared_pool;


alter system flush buffer_cache;

System altered.

PTUSER@orcl>

set autotrace TRACEONLY


SQL> select table_name,tablespace_name,status from tab1 where num_rows > 1000;

->
check stats on table level.

SELECT LAST_ANALYZED FROM DBA_TABLES WHERE TABLE_NAME='TAB1';

Though creating index is not helping to avoid full table scan. Now let us update
table statistics.

begin
dbms_stats.gather_table_stats(
ownname => 'PTUSER',
tabname => 'TAB1',
estimate_percent => 100,
method_opt => 'for all columns size auto',
degree => 3,
cascade => TRUE);
end;
/

alter system flush shared_pool;


alter system flush buffer_cache;

select table_name,tablespace_name,status from tab1 where num_rows > 1000;

-> Still the same with updated stats, Let us try using hint on this query and get
explain plan.
select sql_id,child_number,sql_text from v$sql where sql_Text like '%TAB1%';

alter system flush shared_pool;


alter system flush buffer_cache;

select /*+ INDEX (tab1 tab_num_rows_ind)*/ table_name,tablespace_name,status from


tab1 where num_rows > 1000;

select /*+ INDEX (b tab_num_rows_ind)*/ table_name,tablespace_name,status from tab1


b where b.num_rows>1000;

Still the same performance. Now let us change the value in the filter and check
execution plan
SQL> select table_name,tablespace_name,status from tab1 b where b.num_rows>10000;

corrected query:-
----------------
alter system flush shared_pool;
alter system flush buffer_cache;

select /*+ INDEX (b tab1_num_rows_ind)*/ table_name,tablespace_name,status from


tab1 b where b.num_rows>1000;

Note: cost is gone again

We are using hint to force optimizer to go for index scan. but, optimizer always
will go for better execution plan even though you have index created on it.
it will not use indexes for sometimes because without index also having the better
execution plan ( i mean, by usin full table scan)

Avoiding full table scans:


--------------------------
In this,we will see what a full table scan is, how to avoid it, and when to choose
a full table scan over other methods.

1. Connect to the SH schema:


CONNECT sh/sh
2. Create the MY_SALES_ALL table:
CREATE TABLE sh.MY_SALES_ALL AS
SELECT ROWNUM AS ID, X.* FROM sh.SALES X;

3. Create the MY_SALES_2 table:


CREATE TABLE sh.MY_SALES_2 AS
SELECT * FROM sh.MY_SALES_ALL NOLOGGING;

4. Compute statistics on the tables we just created:


EXEC DBMS_STATS.GATHER_TABLE_STATS('SH', 'MY_SALES_ALL',estimate_percent =>
100,method_opt => 'for all columns size 1');

EXEC DBMS_STATS.GATHER_TABLE_STATS('SH', 'MY_SALES_2',estimate_percent =>


100,method_opt => 'for all columns size 1');

5. Verify the database blocks used by the two tables:


SELECT BLOCKS FROM DBA_TABLES WHERE TABLE_NAME IN ('MY_SALES_ALL', 'MY_SALES_2');

6. Delete some rows from MY_SALES_2, resulting in a table with about 1/100 rows
of the original SALES table:
DELETE FROM sh.MY_SALES_2 WHERE MOD(ID,100) <> 0;
COMMIT;

7. Re-compute statistics on the MY_SALES_2 table:


EXEC DBMS_STATS.GATHER_TABLE_STATS('SH', 'MY_SALES_2',estimate_percent =>
100,method_opt => 'for all columns size 1');

8. Count the database blocks used by MY_SALES_ALL and MY_SALES_2 tables:


SELECT BLOCKS FROM DBA_TABLES WHERE TABLE_NAME IN ('MY_SALES_ALL', 'MY_SALES_2');

9. Select some rows from the MY_SALES_ALL table, showing the execution plan
with statistics:
SET LINESIZE 120
SET AUTOT TRACE EXP STAT
SELECT * FROM sh.MY_SALES_ALL WHERE TIME_ID > TO_DATE('20011220', 'YYYYMMDD');

10. Flush the buffer cache:


CONNECT / AS SYSDBA
ALTER SYSTEM FLUSH BUFFER_CACHE;

11. Select some rows using the same query from MY_SALES_2 table, showing the
execution plan with statistics:
CONNECT sh/oracle
SET LINESIZE 120
SET AUTOT TRACE EXP STAT
SELECT * FROM sh.MY_SALES_2
WHERE TIME_ID > TO_DATE('20011220', 'YYYYMMDD');
SET AUTOT OFF

12. Shrink space on the MY_SALES_2 table:


ALTER TABLE sh.MY_SALES_2 ENABLE ROW MOVEMENT;
ALTER TABLE sh.MY_SALES_2 SHRINK SPACE;

EXEC DBMS_STATS.GATHER_TABLE_STATS('SH', 'MY_SALES_2',estimate_percent =>


100,method_opt => 'for all columns size 1');

13. Count the used database blocks by MY_SALES_ALL and MY_SALES_2 tables after
space shrinking:
SELECT BLOCKS FROM DBA_TABLES WHERE TABLE_NAME IN ('MY_SALES_ALL', 'MY_SALES_2');

14. View some statistics on full table scans:


SELECT NAME, VALUE FROM V$SYSSTAT
WHERE NAME LIKE '%table scan%';

15. Drop the tables created earlier:


DROP TABLE sh.MY_SALES_ALL;
DROP TABLE sh.MY_SALES_2;

Вам также может понравиться