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

    A 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
    A 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

A 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.

Wednesday, 31 January 2024

Extended Statistics

 

Use Extended Statistics For Better SQL Execution Plans

1. https://blogs.oracle.com/optimizer/post/extended-statistics

In real-world data, there is often a relationship or correlation between the data stored in different columns of the same table. For example, consider a customers table where the values in a cust_state_province column are influenced by the values in a country_id column, because the state of California is only going to be found in the United States. If the Oracle Optimizer is not aware of these real-world relationships, it could potentially miscalculate the cardinality estimate if multiple columns from the same table are used in the where clause of a statement. With extended statistics you have an opportunity to tell the optimizer about these real-world relationships between the columns. 

https://blogs.oracle.com/optimizer/post/use-extended-statistics-for-better-sql-execution-plans

select dbms_stats.create_extended_stats(user,'t','(upper(surname))')
from dual;
begin
   dbms_stats.gather_table_stats(user,'t', 
      method_opt=>'for columns (upper(surname))',no_invalidate=>FALSE);
end; /

2. https://blogs.oracle.com/optimizer/post/why-do-i-have-sql-statement-plans-that-change-for-the-worse

Inaccurate Cardinality, Inaccurate Cost

If cardinality estimates are inaccurate, then the calculated costs are likely to be inaccurate too. The resulting execution plan might be suboptimal because it is based on incorrect or missing information. Still, it is essential to remember that this does not mean that a bad execution plan is certain. After all, the optimizer is designed to work around issues like this as much as possible

Tackling the Root Cause

If you have a problem SQL statement, I strongly suggest that you always ask yourself, ‘can I improve the cardinality estimates?’

Here are some ways to do that:

  • Ensure that statistics are present and not stale. Gather statistics regularly to keep them fresh. Hopefully, this is obvious.

  • Create histograms (manually or automatically), especially if there is a known range or value skew.

  • For cases where functions are wrapped around columns and used in query predicates, consider creating virtual columns or function-based indexes. Remember to regather statistics once the column/index has been created.

  • Create extended statistics for expressions and correlated columns.

  • Use dynamic statistics (dynamic sampling) at level 3 or more, especially if SQL statements are relatively long-running and have complex predicates (you can target individual queries or sessions; there is no need to use elevated dynamic sampling levels system-wide)

Tuesday, 9 January 2024

What to look for a slow query in oracle

 

  • Query execution plan: This is a list of steps the database takes when running the query. 
  • Indexes: Indexes are often most useful when created on columns as part of the Join and Where clauses. Check which columns are used, check if they have indexes, and create them if they don't.
  • Statistics: Ensure that the tables and indexes used by the query have up-to-date statistics. You can use the DBMS_STATS package to gather statistics.
  • To get actual cardinality  SELECT /*+ GATHER_PLAN_STATISTICS */ 
  • CPU usage: Use the V$SESSTAT view to determine which session is using the most CPU.  Use V$STATNAME for statistics-id description.
  • Long-running queries: Use the v$session_longops view to find long-running queries.



System-wide response time: Use V$sysmetric;  v$active_session_history, v$sqlArea;
v$sysmetric_summary to measure system-wide response time.

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

To display the execution plan for a specific SQL ID: Use  the dbms_xplan.display_awr procedure.

To Display the execution plan of the last SQL statement 
SET LINESIZE 150 SET PAGESIZE 2000 
SELECT * FROM Table(DBMS_XPLAN.DISPLAY_CURSOR);
 


A db file sequential read wait event occurs when a process requests a single block of data from a datafile and is waiting for the operation to complete. This event is initiated by SQL statements that perform single-block read operations. 

A db file scattered read wait event is a wait for a physical read of multiple Oracle blocks from the disk. It's similar to a db file sequential read, but the session is waiting for a multi-block I/O read request to complete. 
A db file scattered read is usually caused by scanning the entire or a sub-range of a table, index, table partition, or index partition. It's associated with full table scans and index fast full scans (FFS) operations