Thursday, 29 February 2024

Index Rebuild condition

Every so often, we need to rebuild indexes in Oracle, because indexes become fragmented over time. This causes their performance - and by extension - that of your database queries, to degrade. 

There are 2 rules of thumb to help determine if the index needs to be rebuilt:

    1. If the index has height greater than four, rebuild the index.

    2. The deleted leaf rows should be less than 20%.

    3. To re-create an existing index or one of its partitions or subpartitions. If the index is marked unusable, then a successful rebuild will mark it usable.




ALTER INDEX [schema.]index REBUILD  /ONLINE / PARTITION partition  

Wednesday, 28 February 2024

How to trace SQL sessions to identify Oracle Database bottlenecks DBMS_MONITOR

How to trace SQL sessions to identify Oracle Database bottlenecks

   Refer  Blog Theme - Details (oracle.com)

 To start the session trace, you first need to know the unique identifiers of the session: the SID and the SERIAL#. Use the following query

select sid, serial#
from v$session
where username = 'SH';

Using the SID and SERIAL# returned, turn on tracing for the session by executing the following SQL statement as the SYS user:

begin
  dbms_monitor.session_trace_enable (
    session_id => <SID>, 
    serial_num => <serial#>, 
    waits      => true, 
    binds      => true
    plan_stat  => 'all_executions');
end;
/

After tracing is enabled, the trace file— a text file—is generated on the database server at the location specified by the DIAGNOSTIC_DEST database initialization parameter. For RAC Server there can be multiple location.

Now execute the activities need to be Traced...

Then close / disable the Tracing thru dbms_monitor.session_trace_disable.

Run the Tkprof upon the raw trace file xe_ora_<spid>.trc that is generated.

>Tkprof xe_ora_4736.trc xe_ora_4736.out sys=no waits=yes aggregate=no width=180.

Code listing 3: tkprof output, part 1

... output truncated ...
SELECT     sum(s.amount_sold) AS dollars
  FROM     sales s
  ,        times t
  WHERE    s.time_id = t.time_id
  AND      t.calendar_month_desc = '1998-05'
call     count      cpu    elapsed      disk      query    current        rows
————— ———————— ———————— —————————— ————————— —————————— —————————— ———————————
Parse        1     0.00       0.00         0          0          0           0
Execute      1     0.00       0.00         0          0          0           0
Fetch        2     0.00       0.01         0          3          0           1
————— ———————— ———————— —————————— ————————— —————————— —————————— ———————————
total        4     0.00       0.01         0          3          0           1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
—————————— —————————— —————————— ———————————————————————————————————————————
         1          1          1 SORT AGGREGATE (cr=3 pr=0 pw=0 time=61 us)
         1          1          1  MAT_VIEW REWRITE ACCESS FULL CAL_MONTH_
                                  SALES_MV (cr=3 pr=0 pw=0 time=52 us cost=3 
                                  size=15 card=1)
... output truncated …
..




Thursday, 8 February 2024

Forward Declaration in Procedure

Explain the term "forward declaration" in packages.?

When you have a procedure p2 you want to code for whatever reason AFTER you reference it. 
you can "forward declare it"
For example-

ops$tkyte@ORA920LAP> create or replace package demo_pkg
2 as
3 procedure p;
4 end;
5 /

Package created.

and in the body you have this:



ops$tkyte@ORA920LAP>
ops$tkyte@ORA920LAP> create or replace package body demo_pkg
2 as
3 procedure p
4 is
5 begin
6 p2;
7 end;
8
9 procedure p2
10 is
11 begin
12 null;
13 end;
14 end;
15 /

Warning: Package Body created with compilation errors.

ops$tkyte@ORA920LAP> show errors
Errors for PACKAGE BODY DEMO_PKG:

LINE/COL ERROR
-------- -----------------------------------------------------------------
6/3 PLS-00313: 'P2' not declared in this scope
6/3 PL/SQL: Statement ignored

that fails, p doesn't know about p2 yet, so you can:

ops$tkyte@ORA920LAP>
ops$tkyte@ORA920LAP> create or replace package body demo_pkg
2 as
3 procedure p2;

4
5 procedure p
6 is
7 begin
8 p2;
9 end;
10
11 procedure p2
12 is
13 begin
14  p;
15 end;
16 end demo_pkg;
17 /


Package body created.

forward declare p2, but it would be BETTER to just define p2 at the top of the package

What is Oracle Database 12c

 


Oracle Database 12c introduces a new multitenant architecture that makes it easy to deploy and manage database clouds. Oracle 12c is a pluggable database environment, where we can plug multiple databases into single database container. All these databases then share same background processes and memory.


Multitenancy is a reference to the mode of operation of software where multiple independent instances of one or multiple applications operate in a shared environment.


Oracle Database Memory Management

 
Memory Architecture (oracle.com)




Saturday, 3 February 2024

Plan Stability Using SQL Plan Management - Baseline & SqltRpt.sql

Stored OutLines v/s  BaseLines 

Stored outlines also make a plan stable, but they make it rigid. The optimizer identifies that there is an outline for a SQL statement and stops generating new plans. Baselines, on the other hand, never stop the optimizer from generating a new plan.


Stored outlines are deprecated in Oracle 11g. From Oracle 11g onward, you should use SQL Plan Management.

The SQL plan management feature enables you to store validated or well-known plans for SQL statements in the form of baselines, which can be very useful in diagnosing sudden performance degradations. Because the baselines (and the corresponding plans) are stored in a repository, you can also compare them and decide to make the most efficient use of them .

Reference

https://asktom.oracle.com/Misc/oramag/baselines-and-better-plans.html

https://oracle-base.com/articles/11g/sql-plan-management-11gr1

Stored Outlines

https://oracle-base.com/articles/misc/outlines

-- Grant the necessary privileges for outline creation.

CONN sys/password AS SYSDBA

GRANT CREATE ANY OUTLINE TO SCOTT;
GRANT EXECUTE_CATALOG_ROLE TO SCOTT;

-- Create an outline for a specific SQL statement.

CREATE OUTLINE EMP_Dept FOR CATEGORY scott_outlines
ON SELECT e.empno, e.ename, d.dname FROM emp e, dept d 
WHERE e.deptno = d.deptno;

-- Check the outline as been created correctly.

SELECT name, category, sql_text, node, stage, join_pos, hint FROM user_outlines WHERE category = 'SCOTT_OUTLINES';

SELECT node, stage, join_pos, hint FROM user_outline_hints WHERE name = 'EMP_DEPT';

      NODE      STAGE   JOIN_POS HINT
---------- ---------- ---------- --------------------------------------------------
         1          1          0 NO_EXPAND(@"SEL$1" )
         1          1          0 PQ_DISTRIBUTE(@"SEL$1" "E"@"SEL$1" NONE NONE)
         1          1          0 USE_MERGE(@"SEL$1" "E"@"SEL$1")
         1          1          0 LEADING(@"SEL$1"  "D"@"SEL$1" "E"@"SEL$1")
         1          1          0 NO_STAR_TRANSFORMATION(@"SEL$1" )
         1          1          0 NO_FACT(@"SEL$1" "E"@"SEL$1")
         1          1          0 NO_FACT(@"SEL$1" "D"@"SEL$1")
         1          1          2 FULL(@"SEL$1" "E"@"SEL$1")
         1          1          1 INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))
         1          1          0 NO_REWRITE(@"SEL$1" )
         1          1          0 NO_REWRITE(@"SEL$1" )
SQL Plan Management using BaseLine Plan

First, we enable the baseline capture in the session:

alter session set optimizer_capture_sql_plan_baselines = true;

Now all the SQL statements executed in this session will be captured, along with their optimization plans, in the SQL management base. 

Every time the plan changes for a SQL statement, it is stored in the plan history.

-- First execution. Default Environment

select * /* ARUP */ from sales where quantity_sold > 1 order by cust_id;

-- Change the optimizer mode

alter session set optimizer_mode = first_rows;

-- Second execution. Opt Mode changed

select * /* ARUP */ from sales

where quantity_sold > 1 order by cust_id;

 -- Gather stats now

dbms_stats.gather_table_stats (

        ownname            => 'SH',
        tabname             => 'SALES',
        cascade              => TRUE,
        no_invalidate      => FALSE,
        method_opt        => 'FOR ALL INDEXED COLUMNS SIZE AUTO',
        granularity          => 'GLOBAL AND PARTITION',
        estimate_percent => 10, 
        degree                => 4
    );

 -- Third execution. After stats

select * /* ARUP */ from sales where quantity_sold > 1 order by cust_id;

 If the plan changes in each of the executions of the SQL in Listing 1, the different plans will be captured in the plan history for that SQL statement. 

 The easiest way to view the plan history is through Oracle Enterprise Manager. From the Database main page, choose the Server tab and then click SQL Plan Control . 

 From that page, choose the SQL Plan Baseline tab. On that page, search for the SQL statements containing the name ARUP .

The important columns on the screen are as follows:

  • Enabled indicates whether the plan is active.
  • Accepted indicates whether the plan should be considered by the optimizer. If more than one plan is accepted, the optimizer will select the best plan among them.
  • Fixed indicates whether the plan is to be used permanently for that SQL statement. If more than one plan is fixed, the optimizer will select the best plan among them.
  • Auto Purge indicates whether the plan, if unused, will automatically be deleted from the plan history after a specified amount of time. 


Using Baselines

With the SQL plan baselines captured, we now enable the optimizer to use them:

alter session set optimizer_use_sql_plan_baselines = true;

With baseline use enabled, when the optimizer reparses a SQL statement, it examines the plans stored in the baseline for that SQL statement and chooses the best among them. This is where the most important benefit of baselines comes in. The optimizer also still reparses the SQL statements—the presence of a baseline does not prevent that—and if the newly generated plan is not found in the plan history of the SQL, it will be added, but not as “accepted.”

The LOAD_PLANS_FROM_CURSOR_CACHE functions allow SQL statements to be loaded from the cursor cache

DECLARE
  l_plans_loaded  PLS_INTEGER;
BEGIN
  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache( sql_id => '1fkh93md0802n');
END;

 The DBA_SQL_PLAN_BASELINES view provides information about the SQL plan baselines. 

SELECT sql_handle, plan_name, enabled, accepted 
FROM   dba_sql_plan_baselines
WHERE  sql_text LIKE '%spm_test_tab%'
AND    sql_text NOT LIKE '%dba_sql_plan_baselines%';

SQL_HANDLE                     PLAN_NAME                      ENA ACC
------------------------------ ------------------------------ --- ---
SYS_SQL_7b76323ad90440b9       SYS_SQL_PLAN_d90440b9b65c37c8  YES YES

1 row selected.

Evolution

  You can compare the performance of the plans by using the evolve function (in Oracle Enterprise Manager ->   SQL Plan Control page -> SQL Plan Baseline tab 
or using the DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE function from the command line).

 

 SELECT DBMS_SPM.evolve_sql_plan_baseline( sql_handle =>                                                                                'SYS_SQL_PLAN_27a47aa15003759b') 

 FROM   dual;

Code Listing 3: Baseline evolution report

-----------------------------------------------------
Evolve SQL Plan Baseline Report
-----------------------------------------------------

Inputs:
----

  PLAN_LIST   = SYS_SQL_PLAN_27a47aa15003759b
  TIME_LIMIT = DBMS_SPM.AUTO_LIMIT
  VERIFY        = YES
  COMMIT       = YES

Plan: SYS_SQL_PLAN_27a47aa15003759b
----------------------

  Plan was verified: Time used 41.06 seconds.
  Failed performance criterion: Compound improvement ratio < .36

                       Baseline Plan       Test Plan   Improv. Ratio

                       --------------      ---------   -------------

  Execution Status:          COMPLETE       COMPLETE
  Rows Processed:                   0              0
  Elapsed Time(ms):              5036           1033         4.88
  CPU Time(ms):                   254            700          .36
  Buffer Gets:                   1728          43945          .04
  Disk Reads:                     254             22        11.55
  Direct Writes:                    0              0
  Fetches:                         49             22         2.23
  Executions:                       1              1

--------------------------------------------------------------------
Report Summary
--------------------------------------------------------------------

Number of SQL plan baselines verified: 1.

Number of SQL plan baselines evolved: 0.

Failed performance criterion:

Compound improvement ratio < .36. 

The line clearly shows that the newly considered plan performed worse than the original plan so it was rejected as a replacement for the optimizer‘s best plan choice.  Had the comparison ratio yielded an improvement factor greater than 1, SQL plan management would have accepted that plan as a candidate for the optimizer to consider.

Another example from https://oracle-base.com/articles/11g/sql-plan-management-11gr1

Plan: SYS_SQL_PLAN_d90440b9ed3324c0
-----------------------------------
  Plan was verified: Time used .05 seconds.
  Passed performance criterion: Compound improvement ratio >= 15.4.
  Plan was changed to an accepted plan.

                      Baseline Plan      Test Plan     Improv. Ratio
                      -------------      ---------     -------------
  Execution Status:        COMPLETE       COMPLETE

DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(SQL_HANDLE=>'SYS_SQL_7B76323AD90440B9')
--------------------------------------------------------------------------------
  Rows Processed:                 1              1
  Elapsed Time(ms):               2              0
  CPU Time(ms):                   2              0
  Buffer Gets:                   46              3             15.33
  Disk Reads:                     0              0
  Direct Writes:                  0              0
  Fetches:                        0              0
  Executions:                     1              1

-------------------------------------------------------------------------------
                                 Report Summary

DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(SQL_HANDLE=>'SYS_SQL_7B76323AD90440B9')
--------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Number of SQL plan baselines verified: 1.
Number of SQL plan baselines evolved: 1.

Here, in this example we can see the improvement of new plan by 15.33 . So the plan will also be 
accepted by dba_sql_Plan_baseline  .

What if you feel that the decision made by the evolve function is not accurate and you would rather force the optimizer to use a specific plan? You can do that by making the plan fixed in the baseline. You can make a plan fixed by executing the alter_sql_plan_baseline function in the dbms_spm package, as shown in Listing 4.

 Code Listing 4: Fixing a plan baseline 

 declare
   l_plans pls_integer;
begin
   l_plans := dbms_spm.alter_sql_plan_baseline (
      sql_handle         => 'SYS_SQL_f6b17b4c27a47aa1',
      plan_name         => 'SYS_SQL_PLAN_27a47aa15003759b',
      attribute_name   => 'fixed',
      attribute_value  => 'YES'
   );
end;


Another method for baseLine evolution is using  @$dbhome$/rdbms/admin/sqltrpt.sql  <sql-id>, passing sql_id.  You will get the below reports and finding--

 https://www.youtube.com/watch?v=OdkFPXj9RMU&t=212s


 



Then use the dbms_sqltune.create_sql_plan_baseline(task=? , owner=>sys, plan_hash_value=>?);


Buffer Modes and States and I/O

Buffer States

The database uses internal algorithms to manage buffers in the cache.

A buffer can be in any of the following mutually exclusive states:

  • Unused

    The buffer is available for use because it has never been used or is currently unused. This type of buffer is the easiest for the database to use.

  • Clean

    This buffer was used earlier and now contains a read-consistent version of a block as of a point in time. The block contains data but is "clean" so it does not need to be checkpointed. The database can pin the block and reuse it.

  • Dirty

    The buffer contain modified data that has not yet been written to disk. The database must checkpoint the block before reusing it.

Every buffer has an access mode: pinned or free (unpinned). A buffer is "pinned" in the cache so that it does not age out of memory while a user session accesses it. 

 

Buffer Modes

When a client requests data, Oracle Database retrieves buffers from the database buffer cache in either current mode or consistent mode.

The modes differ as follows:

  • Current mode

    current mode get, also called a db block get, is a retrieval of a block as it currently appears in the buffer cache. For example, if an uncommitted transaction has updated two rows in a block, then a current mode get retrieves the block with these uncommitted rows. 

  • Consistent mode
    consistent read get is a retrieval of a read-consistent version of a block. This retrieval may use undo data. For example, if an uncommitted transaction has updated two rows in a block, and if a query in a separate session requests the block, then the database uses undo data to create a read-consistent version of this block (called a consistent read clone) that does not include the uncommitted updates. Typically, a query retrieves blocks in consistent mode.


Buffer I/O

logical I/O, also known as a buffer I/O, refers to reads and writes of buffers in the buffer cache.

When a requested buffer is not found in memory, the database performs a physical I/O to copy the buffer from either the flash cache or disk into memory. The database then performs a logical I/O to read the cached buffer.