Performance Issue Scenarios and Activities
Performance Issue Scenarios and Activities
Performance Issue Scenarios and Activities
—--------------------------------------------------------------------------------------
This will block the second session until the first session has done its work.
1. Simulation
3. Solution
1. Simulation
Session 1:
Table created.
1 row created.
SQL> commit;
Commit complete.
SQL>
SQL> select sys_context('USERENV','SID') from dual;
SYS_CONTEXT('USERENV','SID')
----------------------------------------------------
46
SQL>
Session 2:
In second session try to update the rows which you have selected
above.
SYS_CONTEXT('USERENV','SID')
---------------------------------------------------
39
SQL>
SQL> update t set a='x' where a='z';
-- hanging here --
..
..
-- OR --
-- OR --
SELECT
s.blocking_session,
s.sid,
s.serial#,
s.seconds_in_wait
FROM
gv$session s
WHERE
blocking_session IS NOT NULL;
-- OR --
SELECT
l1.sid || ' is blocking ' || l2.sid blocking_sessions
FROM
gv$lock l1, gv$lock l2
WHERE
l1.block = 1 AND
l2.request > 0 AND
l1.id1 = l2.id1 AND
l1.id2 = l2.id2;
-- OR --
Output:
BLOCKING_STATUS
---------------------------------------------------------------------
-------------
SH@rac2.rajasekhar.com ( SID=46 ) is blocking SH@rac2.rajasekhar.com
( SID=39 )
SQL>
SQL>
-- OR --
SESS ID1
ID2 LMODE REQUEST TY
------------------------------------------------ ----------
---------- ---------- ---------- --
Holder: 46 589826
1571 6 0 TX
Waiter: 39 589826
1571 0 6 TX
SQL>
-- OR --
SQL> SELECT
s.blocking_session,
s.sid,
s.serial#,
s.seconds_in_wait
FROM
gv$session s
WHERE
blocking_session IS NOT NULL; 2 3 4 5 6 7 8
9
SQL>
-- OR --
SQL> SELECT
l1.sid || ' is blocking ' || l2.sid blocking_sessions
FROM
gv$lock l1, gv$lock l2
WHERE
l1.block = 1 AND
l2.request > 0 AND
l1.id1 = l2.id1 AND
l1.id2 = l2.id2; 2 3 4 5 6 7 8 9
BLOCKING_SESSIONS
----------------------------------------------------------
46 is blocking 39
SQL>
3. Solution
--- OR ----
System altered.
SQL>
1 row updated.
2. About *_TAB_MODIFICATIONS
3. Identify STALE STATS
4. Gather STATS
5. SYSTEM STATISTICS
Introduction
User Objects
Columns
Dictionary
Oracle monitors the DML activity for all tables and records it in the
SGA.
Gather statistics less often and with a very large sample size
Recommended syntax
/*
Assuming we want Oracle to determine where to put histograms (instead
of specifying the list manually):
*/
About *_TAB_MODIFICATIONS
When querying *_TAB_MODIFICATIONS view you should ensure that you run
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO before doing so in order to
obtain accurate results.
Before
-- exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO; --
no rows selected
SQL>
After
BIG_TABLE 100 0 0
SQL>
select
OWNER,TABLE_NAME,PARTITION_NAME,SUBPARTITION_NAME,NUM_ROWS,LAST_ANALY
ZED from DBA_TAB_STATISTICS where STALE_STATS='YES';
OR
CASCADE => TRUE : Gather statistics on the indexes as well. If not used Oracle will
determine whether to collect it or not.
FOR COLUMNS SIZE AUTO : You can specify one column between “” instead of all
columns.
FOR ALL COLUMNS SIZE REPEAT : Prevent deletion of histograms and collect it only
for columns already have histograms.
FOR ALL COLUMNS SIZE SKEWONLY : Collect histograms for columns have skewed
value should test skewness first
FOR ALL INDEXED COLUMNS : Collect histograms for columns have indexes only.
DATABASE Level
Gathering statistics for all objects in database, cascade will include indexes
exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
OR
EXEC
DBMS_STATS.GATHER_DATABASE_STATS(ESTIMATE_PERCENT=>DBMS_STATS.AUTO_SA
MPLE_SIZE,degree=>6);
OR
EXEC
DBMS_STATS.GATHER_DATABASE_STATS(ESTIMATE_PERCENT=>dbms_stats.auto_sa
mple_size,CASCADE => TRUE,degree => 4);
SCHEMA level
set timing on
exec dbms_stats.gather_schema_stats(ownname=>'&schema_name',
CASCADE=>TRUE,ESTIMATE_PERCENT=>dbms_stats.auto_sample_size,degree
=>4);
OR
exec
dbms_stats.gather_schema_stats(ownname=>'&schema_name',ESTIMATE_PERCE
NT=>dbms_stats.auto_sample_size,degree =>4);
OR
TABLE Level
-- The CASCADE parameter determines whether or not statistics are
gathered for the indexes on a table.
exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
exec
dbms_stats.gather_table_stats(ownname=>'&Schema_name',tabname=>'&Tabl
e_name',estimate_percent=>DBMS_STATS.AUTO_SAMPLE_SIZE,cascade=>TRUE,d
egree =>4);
OR
exec dbms_stats.gather_table_stats('&SCHEMA_NAME','&Table_name');
Index Statistics
NOWORKLOAD statistics:
This will simulates a workload -not the real one but a simulation-
and will not collect full statistics, it's less accurate than
"WORKLOAD statistics" but if you can't capture the statistics during
a typical workload you can use noworkload statistics.
WORKLOAD statistics:
Once the workload window ends after 1,2,3.. hours or whatever, stop
the system statistics gathering:
sreadtim: The Single Block Read Time statistic shows the average
time for a random single block read.
Table created.
SQL> SELECT stattype_locked FROM dba_tab_statistics WHERE
table_name='RAJ' and owner='SH';
STATT
-----
SQL>
2. Lock stats
SQL>
3. Verify
SQL> SELECT stattype_locked FROM dba_tab_statistics WHERE
table_name='RAJ' and owner='SH';
STATT
-----
ALL <---- Hence table locked. It will not allow to gather stats on
this table
SQL>
ERROR at line 1:
4. Unlock
SQL> exec dbms_stats.unlock_table_stats('SH', 'RAJ');
STATT
-----
SQL>
Locked: ALL
Unlocked: NULL
Generate Explain Plan
Generate/Customize
Explain Plan
0. Creating a Plan Table
5. Using DBMS_XPLAN.DISPLAY_CURSOR
The first thing you will need to do is make sure you have a table
called PLAN_TABLE available in your schema.
The following script will create it for you if you don't have it
already
@$ORACLE_HOME/rdbms/admin/utlxplan.sql
SET TIMING ON
set echo on
set linesize 200 pagesize 1000
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
output
=======
SQL> explain plan for select count(*) from test t1, test t2 where
t1.c=t2.c and t1.c=1;
Explained.
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
--------------------
---------------------------------------------------------------------
-----------------
| 1 | SORT AGGREGATE | | 1 | 6 |
| |
---------------------------------------------------------------------
-----------------
---------------------------------------------------
2 - access("T1"."C"="T2"."C")
3 - filter("T1"."C"=1)
4 - filter("T2"."C"=1)
18 rows selected.
SQL>
SET TIMING ON
set echo on
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
@$ORACLE_HOME/rdbms/admin/utlxpls.sql
output
======
SQL> explain plan for select count(*) from test t1, test t2 where
t1.c=t2.c and t1.c=1;
Explained.
SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql
..
..
SQL>
SQL> Rem
SQL> Rem Use the display table function from the dbms_xplan package
to display the last
SQL> Rem explain plan. Force serial option for backward compatibility
SQL> Rem
---------------------------------------------------------------------
-------------------
---------------------------------------------------------------------
-----------------
---------------------------------------------------------------------
-----------------
| 1 | SORT AGGREGATE | | 1 | 6 |
| |
---------------------------------------------------
2 - access("T1"."C"="T2"."C")
3 - filter("T1"."C"=1)
4 - filter("T2"."C"=1)
18 rows selected.
SQL>
SET TIMING ON
set echo on
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
FROM PLAN_TABLE
START WITH id = 0
ORDER BY id;
Output
=======
SQL> SELECT cardinality "Rows",
2 3 FROM PLAN_TABLE
6 START WITH id = 0
8 ORDER BY id;
Rows Plan
----------
--------------------------------------------------------------
1 SELECT STATEMENT
1 SORT AGGREGATE
(OR)
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
Explained.
Elapsed: 00:00:00.01
5 OBJECT_TYPE PLAN,
6 COST
7 FROM PLAN_TABLE
PLAN COST
-------------------------------------------- --------------
SORT AGGREGATE
Elapsed: 00:00:00.00
SQL>
We could have also been set to NULL to produce the same result
set echo on
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
Output
=======
SQL> select count(*) from test t1, test t2 where t1.c=t2.c and
t1.c=1;
COUNT(*)
----------
400000000
SQL> SELECT * FROM
TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'TYPICAL'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
------------------
-------------------------------------
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1
---------------------------------------------------------------------
-----------------
---------------------------------------------------------------------
-----------------
| 1 | SORT AGGREGATE | | 1 | 6 |
| |
|* 2 | HASH JOIN | | 400M| 2288M| 1928
(99)| 00:00:24 |
---------------------------------------------------------------------
-----------------
---------------------------------------------------
2 - access("T1"."C"="T2"."C")
3 - filter("T1"."C"=1)
4 - filter("T2"."C"=1)
23 rows selected.
SQL>
-----
set echo on
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1;
----
set echo on
Output
=======
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
------------------
SQL_ID dkz7v96ym42c6
--------------------
select count(*) from test t1, test t2 where t1.c=t2.c and t1.c=1
---------------------------------------------------------------------
-----------------
---------------------------------------------------------------------
-----------------
---------------------------------------------------------------------
-----------------
16 rows selected.
Rebuild Index Script
racle provides a fast index rebuild capability that allows you to re-create an index
without having to drop the existing index. The currently available index is used as the
data source for the index, instead of the table’s being used as the data source. During
the index rebuild, you can change its STORAGE parameters and TABLESPACE
assignment.
In the following example, the BA_PK index is rebuilt (via the REBUILD clause). Its
storage parameters are changed to use an initial extent size of 8MB and a next extent
size of 4MB in the BA_INDEXES tablespace.
NOTE
When the BA_PK index is rebuilt, there must be enough space for both the old index
and the new index to exist simultaneously. After the new index has been created, the
old index will be dropped.When you create an index that is based on previously indexed
columns, Oracle may be able to use the existing indexes as data sources for the new
index. The Oracle Optimizer may use parts of existing composite indexes as needed for
queries, so you may not need to create many indexes to support the most common
queries.
You can rebuild indexes while they are being accessed via the REBUILD ONLINE
clause of the ALTER INDEX command.