Subscribe to Posts by Email

Subscriber Count

    705

Disclaimer

All information is offered in good faith and in the hope that it may be of use for educational purpose and for Database community purpose, but is not guaranteed to be correct, up to date or suitable for any particular purpose. db.geeksinsight.com accepts no liability in respect of this information or its use. This site is independent of and does not represent Oracle Corporation in any way. Oracle does not officially sponsor, approve, or endorse this site or its content and if notify any such I am happy to remove. Product and company names mentioned in this website may be the trademarks of their respective owners and published here for informational purpose only. This is my personal blog. The views expressed on these pages are mine and learnt from other blogs and bloggers and to enhance and support the DBA community and this web blog does not represent the thoughts, intentions, plans or strategies of my current employer nor the Oracle and its affiliates or any other companies. And this website does not offer or take profit for providing these content and this is purely non-profit and for educational purpose only. If you see any issues with Content and copy write issues, I am happy to remove if you notify me. Contact Geek DBA Team, via geeksinsights@gmail.com

Pages

Quick Question: Check for performance issues

Updated answers

ORA-00600: internal error code, arguments: [13030], [20],

Learnt new thing today, thanks to my colleague Gagan.

Alert log showing this error, whilst checking the trace shows an update statement into a table which is capturing the sid,serial# from gv$session.

So then why ora-600, As per metalink note:-
Ora-00600 [13030], [20] During Update Statement Using V$ tables [ID 1400439.1]

For updates we use a 3 pass algorithm which relies on consistent read. If the first pass does not succeed then we use a CR scan and lock the rows returned, then reset the row source and use a further CR scan at the same snapshot SCN to update those locked rows. The V$ view in the WHERE clause does not support CR and so each scan using the same snapshot SCN may see different data depending on the content of V$SESSION at the scan time which completely breaks the update algorithm. The errors you see (ORA-600 [13030]) indicate:
[1] - the row to be updated has changed values in comparison columns
[2] - the row to be updated does not exist
These are the sorts of error you can get if the separate scans at the same snapshot SCN return different data, as can occur with a V$ view involved.

Finally, the V$views are not read consistent hence we cannot use them directly to capture the things

The solution would be create a table, insert into that table with the values from v$session and then update the records in the table we created if req.

What I have learnt, the algorithm for updates, three pass which relies on consistent read. and CR scan again reads to that SCN snapshot to update the locks, where the V$views are not consistent read its breaking the algorithm.

Nice note!!!!
-Thanks
Geek DBA

Undo backup optimization in 11g

Another little feature in 11g is undo backup optimization.

Prior to Oracle 11g, RMAN always backed up all UNDO with a full backup, including UNDO for committed blocks.

However in 11g, RMAN is able to skip the UNDO information for those blocks that are already committed and exceeded undo_retnention threshold.

This optimization brings in 11g to skip those undo blocks that are not needed for recovery operation. This allows backup of undo TS should be quicker and save some storage.

Further, there is a bug or behavior change that,

Bug 6399468: UNDO OPTIMIZATION
====> Undo optimization was changed from 'all undo not needed' to 'undo not in use older than 1 hour' ====> Undo optimization was changed from 'all undo not needed' to 'undo not in use older than 1 hour'
In unpublished bug , the Undo optimization was changed from 'all undo not needed' to 'undo not in use older than 1 hour'.

You can test the UNDO backup optimization by
1) Take a backup of UNDO TS via RMAN, note down the size
2) Do a massive transaction
3) Commit
4) Sleep for certain seconds
5) Take a backup of UNDO TS again, node down the size -, you might see here that UNDO TS size is not reduced
6) This is due to the bug mentioned above, where undo will only skip the changes that done past 1 hour. So lets try again

1) Take a backup of UNDO TS via RMAN, note down the size
2) Do a massive transaction
3) Commit
4) Sleep for certain seconds using dbms_lock.sleep(3600); --> 1 Hour
5) Take a backup of UNDO TS again, node down the size of backup --> now you may see the reduced size of file from the Step 1 above.
6) Your backup optimization is working.

-Thanks
Geek DBA

Quick Question: Check for performance issues

Hello Everyone,

Thanks to Satish / Shanawaz for sharing this piece.

What if , if you been assigned on,

A brand new database with new application designed , new tables and short volume of data, asked you to verify the database performance and provide suggestions and recommendations for any improvements. You can assume this is just passed development stage and entered into UAT stage.

  • Where do you start?
  • What you would like to check?
  • Which approach you follow?
  • What kind of tools you would use?

Please comment your thoughts. Your comments will be more helpful to provide more piece of information than I have.

Stay tuned….

Update 18-Mar-2013,

Sorry Friends for the delay.

Here you go with answers (This may vary depends on environment to environment but this is how I start with)

Where do you start?

Memory Advisories and OS level stuff & individual statements to tune

What you would like to check?

Statements that need to tune

AWR Reports of the time that testing has happened

ADDM Reports of the time that testing has happened

Which approach you follow?

Top down approach

Start with OS level and drill down to Individual SQL Tuning

What kind of tools you would use?

AWR, ADDM, OS Tools orca, plexus, Sql Tuning advisory, SQL Performance Analyzer to compare the changes etc.

Well out of all above, two things for sure I would like to do,

1) Memory Advisories

http://db.geeksinsight.com/tools-scripts/memory-advisories/

This should be run when you have a peak load or you can get the same from the AWR report as well. With this we can find whether the SGA is adequate or not and any increase in sga would benefit to reduce the physical reads or gets etc.

We have SGA, Buffer Cache, PGA,Shared pool, Streams Pool advisories etc

2) Analyze the Database SQL Performance as its a new design (probably a prototype product database) using SQL Tuning advisor or the SQL access advisory

Basically, SQL Tuning advisor can run for a single statement or a set of SQL Statements which can give you the results as recommendations to create indexes, include parallelism, gather statistics, create profiles and show you the benefit of the recommendations when implemented.

Where in the SQL access advisory would not give you that it only show the recommendations mainly to create indexes or materialized view not even the percentage of benefits you get.

Let check how to use STA/SAA, (Thanks Shanawaz for providing this steps)

Steps here:- https://http://db.geeksinsight.com/tools-scripts/sql-tuning-advisory-sql-access-advisory-steps/

If you look at the outputs provided, more than 149 statements has been analyzed, 40+ index creation recommendations provided and more than 60+ objects gather statistics has been recommended, and some error out.

With this you can well analyze how the queries or performing in terms of optimizer perspective not from the database/developer perspective. Since the developer may not know how optimizer chooses its plan based on best available statistics.

-Geek DBA

RHEL 6.4: ASMLib Availability

From the release notes:- https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/6/html-single/6.4_Release_Notes/index.html

 

As we aware that Oracle didn’t shipped the ASMLIB for RHEL, to progress on that, RHEL has came up with similar modules.

Oracle ASMLib Availability and Support

Oracle ASM (Automated Storage Management) is a data volume manager for Oracle databases. ASMLib is an optional utility that can be used on Linux systems to manage Oracle ASM devices. ASMLib consists of the following components:

  • kmod-oracleasm (open-source (GPL) kernel module package)

  • oracleasm-support (open-source (GPL) utilities package)

  • oracleasmlib (proprietary library package)

ASM features and functionality are available without ASMLib. The use of ASMLib does not affect database performance. The ASMLib kernel module package is now available in the Red Hat Enterprise Linux 6 Supplementary RHN channel. Red Hat Enterprise Linux 6 customers who use ASMLib can obtain the other two components using the instructions in the following KnowledgeBase article:

https://access.redhat.com/knowledge/solutions/315643

The ASMLib kernel module package is provided for the convenience of our customers but is not supported, nor are the ABIs guaranteed per Red Hat's Supplementary software package support terms available at:

https://access.redhat.com/support/offerings/production/scope_moredetail.html

Please note that Red Hat is continuing to develop fully open-source alternatives to ASMLib. Red Hat has provided a reference architecture for Oracle RAC clusters using upstream-accepted technologies such as dm-multipath and udev. This reference architecture is available at:

https://access.redhat.com/knowledge/articles/216093

Find your statistics jobs windows-groups-status etc.

Atleast I found hard checking in many other areas,hence writing this

You may not find the no rows for gather_stats_job in 11g due to the enhancments in maintainence groups.

The collection of statistics along with some other maintainence tasks have been incorporated in to dba auto task admin client procedure

First you need to see whether they auto task admin in database or not.

SQL> SELECT client_name, status, mean_job_duration FROM dba_autotask_client;  2
CLIENT_NAME                                                      STATUS   MEAN_JOB_DURATION
---------------------------------------------------------------- -------- -------------------------------- 
auto optimizer stats collection                                  ENABLED  +000000000 00:03:25.541666667
auto space advisor                                               ENABLED  +000000000 00:02:28.150000000
sql tuning advisor                                               ENABLED  +000000000 00:45:18.733333333

set linesize 121
col client_name format a35
col consumer_group format a25
col service_name format a15
col window_group format a20
SQL> SELECT client_name, status, consumer_group, window_group FROM dba_autotask_client;

CLIENT_NAME                         STATUS   CONSUMER_GROUP            WINDOW_GROUP
----------------------------------- -------- ------------------------- --------------------
auto optimizer stats collection     ENABLED  ORA$AUTOTASK_STATS_GROUP  ORA$AT_WGRP_OS
auto space advisor                  ENABLED  ORA$AUTOTASK_SPACE_GROUP  ORA$AT_WGRP_SA
sql tuning advisor                  ENABLED  ORA$AUTOTASK_SQL_GROUP    ORA$AT_WGRP_SQ

Note:- If not run, $ORACLE_HOME/rdbms/admin/dbmsatsk.sql

Drill down to Scheduler window groups

SQL> SELECT * FROM DBA_SCHEDULER_WINDOW_GROUPS;

WINDOW_GROUP_NAME              ENABL NUMBER_OF_WINDOWS NEXT_START_DATE                       
------------------------------ ----- ----------------- -------------------------------------
MAINTENANCE_WINDOW_GROUP       TRUE                  7 07-MAR-13 22.00.00.000000 GB-EIRE    
ORA$AT_WGRP_OS                 TRUE                  7 07-MAR-13 22.00.00.000000 GB-EIRE    
ORA$AT_WGRP_SA                 TRUE                  7 07-MAR-13 22.00.00.000000 GB-EIRE    
ORA$AT_WGRP_SQ                 TRUE                  7 07-MAR-13 22.00.00.000000 GB-EIRE    

Further drill down to scheduler windows

SQL> select WINDOW_NAME,RESOURCE_PLAN, REPEAT_INTERVAL,DURATION,ENABLED,ACTIVE from dba_scheduler_windows;
WINDOW_NAME            REPEAT_INTERVAL                          DURATION         ENABL ACTIV
---------------------- ---------------------------------------- ---------------------- -----
MONDAY_WINDOW          freq=daily;byday=MON;byhour=22;byminute= +000 04:00:00    TRUE  FALSE
                       0; bysecond=0

TUESDAY_WINDOW         freq=daily;byday=TUE;byhour=22;byminute= +000 04:00:00    TRUE  FALSE
                       0; bysecond=0

WEDNESDAY_WINDOW       freq=daily;byday=WED;byhour=22;byminute= +000 04:00:00    TRUE  FALSE
                       0; bysecond=0

THURSDAY_WINDOW        freq=daily;byday=THU;byhour=22;byminute= +000 04:00:00    TRUE  FALSE
                       0; bysecond=0

FRIDAY_WINDOW          freq=daily;byday=FRI;byhour=22;byminute= +000 04:00:00    TRUE  FALSE
                       0; bysecond=0

SATURDAY_WINDOW        freq=daily;byday=SAT;byhour=6;byminute=0 +000 20:00:00    TRUE  FALSE
                       ; bysecond=0

SUNDAY_WINDOW          freq=daily;byday=SUN;byhour=6;byminute=0 +000 20:00:00    TRUE  FALSE
                       ; bysecond=0

WEEKNIGHT_WINDOW       freq=daily;byday=MON,TUE,WED,THU,FRI;byh +000 08:00:00    FALSE FALSE
                       our=22;byminute=0; bysecond=0

WEEKEND_WINDOW         freq=daily;byday=SAT;byhour=0;byminute=0 +002 00:00:00    FALSE FALSE
                       ;bysecond=0

Now check the scheduler run details

SQL> select job_name,status,run_duration,log_date from dba_scheduler_job_run_details 
 where job_name like '%ORA%' and rownum 
Note: When the scheduler window started it will create a job name like above 
OS stands for Optimizer Statistics
SQ stands for SQL Tuning Advisory
SA stands for Segment Advisory


JOB_NAME                 STATUS      RUN_DURATION      LOG_DATE
----------------------------------------------------- -----------------------------------
ORA$AT_SA_SPC_SY_842     SUCCEEDED   +000 00:03:27     06-FEB-13 22.03.29.006418 +00:00
ORA$AT_SA_SPC_SY_7       SUCCEEDED   +000 00:00:26     06-JAN-13 14.09.45.682518 +00:00
ORA$AT_SA_SPC_SY_22      SUCCEEDED   +000 00:00:26     06-JAN-13 22.10.04.505120 +00:00
ORA$AT_OS_OPT_SY_821     SUCCEEDED   +000 00:03:39     05-FEB-13 22.03.41.418487 +00:00
ORA$AT_SQ_SQL_SW_3       SUCCEEDED   +000 00:50:03     06-JAN-13 06.50.05.276734 +00:00
ORA$AT_OS_OPT_SY_21      SUCCEEDED   +000 00:00:35     06-JAN-13 22.10.13.355621 +00:00
ORA$AT_OS_OPT_SY_4       SUCCEEDED   +000 00:00:37     06-JAN-13 10.09.45.396471 +00:00
ORA$AT_OS_OPT_SY_8       SUCCEEDED   +000 00:00:33     06-JAN-13 18.10.01.547017 +00:00
ORA$AT_SQ_SQL_SW_843     SUCCEEDED   +000 00:56:18     06-FEB-13 22.56.20.397311 +00:00

9 rows selected.

SQL>

Another way to find scheduler run of your statistics

SQL>  select operation||decode(target,null,null,'-'||target) operation
,to_char(start_time,'YYMMDD HH24:MI:SS.FF4') start_time
,to_char(  end_time,'YYMMDD HH24:MI:SS.FF4') end_time
from dba_optstat_operations where operation='gather_database_stats(auto)'
order by start_time desc
  /

operation(on)                            START_TIME                END_TIME
---------------------------------------- ------------------------- -------------------------
gather_database_stats(auto)              130210 18:00:38.0680      130210 18:00:50.3929
gather_database_stats(auto)              130210 14:00:30.2518      130210 14:00:50.9174
gather_database_stats(auto)              130210 10:00:22.7646      130210 10:00:48.2924
gather_database_stats(auto)              130210 06:00:02.7987      130210 06:01:55.7652
gather_database_stats(auto)              130209 06:00:02.7911      130209 06:01:53.6289
gather_database_stats(auto)              130208 22:00:02.5849      130208 22:10:12.5439
gather_database_stats(auto)              130207 22:00:03.0104      130207 22:08:29.8338
gather_database_stats(auto)              130206 22:00:02.9352      130206 22:03:22.9765
gather_database_stats(auto)              130205 22:00:03.2965      130205 22:03:41.3111
gather_database_stats(auto)              130204 22:00:02.4189      130204 22:20:01.9220

-Thanks
Geek DBA

12c database: New features list

The below is Gathered from various sources and listed out here, thanks to all who shared those in their respective blogs, Optimizer Blog, Tim hall, Ask Tom etc.

Core Architecture Changes:-

  • Container & Pluggable Databases – 
  • New parameter PGA_AGGREGATE_LIMIT, to limit the pga memory utilization
  • New role CDB Administrator has been introduced
  • Multi threaded database with parameter threaded_executions
  • Multiple LGWR processes for each PDB’s and can share master container LGWR process.

    Few SQL/PLSQL Changes:-

  • Duplicate indexes, One can create duplicate indexes, earlier we use to get error if we are creating a index on same columns which already had index, now you can create index on same columns but with different leading column
  • Increase in the datatype limit to 32K for varchar2,nvarchar2, RAW
  • Invisible columns, you can make columns invisible
  • Identity columns, (same as like sequences but inline with table definition, no need of seperate sequence object and trigger to increment it)

Some Administrative changes:-

  • No bounce for modifying database to archivelog mode
  • No redo for datapump import
  • Temporary global tables will not generate redo
  • Centralized patching.
  • Datafile maintenance is online, no offline required to modify/move the datafile
  • Truncate command enhanced to truncate the child rows as well
  • UNDO for temporary tables can now be managed in TEMP, rather than the regular UNDO tablespace.
  • Reduces contents of regular UNDO, allowing better flashback operations.
  • Reduces the size of redo associated with recovering the regular UNDO tablespace.

    Partitioning Enhancements:- (Tim hall)

  • Asynchronous Global Index maintenance for DROP and TRUNCATE. Command returns instantly, but index cleanup happens later.
  • Cascade for TRUNCATE and EXCHANGE partition.
  • Multiple partition operations in a single DDL
  • Online move of a partition(without DBMS_REDEFINTIION).
  • Interval + Reference Partitioning.

Security Enhancements:-

  • Monitor the privilege assignments easy now with DBMS_PRIVILEGE_CAPTURE
  • Separation of Duties:
    - SYSDBA – Super user
    - SYSOPER – More limited than SYSDBA, but still very powerful.
    - SYSBACKUP – Just enough to do a backup.
    - SYSDG – Just enough for data guard administration.
    - SYSKM – Just enough to perform basic key management tasks.
    - Roles for audit management

Notable changes in Compression:- (Tim hall)

  • Advanced Row compression (for Hot Data).
  • Columnar Query compression (for Warm Data).
  • Columnar Archive compression (for Archive Data).

New things in Data Guard 12c: (Tim hall)

  • Oracle Database 12c introduces a new redo transportation method which omits the acknowledgement (to primary) of the transaction on the standby. This feature is called "Fast Sync" redo transport.
  • Creating a new type of redo destination called "Far Sync Standby". A "Far Sync Standby" is composed only of the standby control files, the standby redo logs and some disk space for archive logs which shall be sent to the Standby database. Failover & Switchover operations are totally transparent as the "Far Sync Standby" cannot be used as the target.
  • Global temporary tables can be possible in dataguard environment

    Statistics Enhancements:-

  • CTAS and INSERT … SELECT automatically compute stats.
  • Global temporary tables can have session level statistics
  • Some dynamic sampling operations are persistent, so they are not lost when the SQL is aged out.
  • Hybrid histograms. When the number of distinct values is greater than 254, “almost popular” values can get “lost” in the mix. A single bucket can now store the popularity of than value, effectively increasing the number of buckets, without actually increasing it.Possible the max number of buckets can be increased based on a parameter.

      Optimizer Enhancements:- Source optimizer blog

  • Oracle database 12c is the first step on the way to making an adaptive, or self-learning optimiser.

Alternative subplans are precomputed and stored in the cursor, so no new hard parsing will be needed as part of the adaption of an already executing plan. Statistics collectors are included in the plan execution. If the collectors cross a threshold, the plan might switch during execution from a nested loops to a hash join.

You can see information about the adaptive actions that have occurred using the DBMS_XPLAN package, with the format of “+all_dyn_plan +adaptive”. If a plan has been adapted, you will see it indicated in the v$sql.is_resolved_dynamic_plan column.

If this functionality scares you, you can turn it off using the OPTIMIZER_APADPTIVE_REPORTING_ONLY parameter. Same work is done, but no actual adaptive action is taken.

During parallel execution, collectors can influence the distribution method (HASH > Distribution). Shown in the plan as the HYBRID HASH operations.

Dynamic statistics replace dynamic sampling. The resulting stats are cached as SHARED DYNAMIC STATS specific for the statement, including the bind values. This information is used for any session using the same statement.

Cardinality feedback can be used to re-optimize subsequent operations. Join statistics are monitored. Works with adaptive cursor sharing. Persisted on disk. New column v$sql.is_reoptimizable shows that a subsequent run will take this into consideration. Collectors are kept, even if the SQL statement is killed part way through. The plan shows that cardinality feedback is used.

SQL Plan Directives are based on a SQL phrase (a specific join) rather than the whole statement. Cached in the directive cache, but persisted in the SYSAUX tablespace. Managed using the DBMS_SPD package.

Information gathered by the optimizer, may prompt automatic creation of column groups, so next time stats are gathered, the extended stats will be gathered.

-Thanks

Geek DBA

12c Database: Threaded executions ?

Oracle may introduce or leverage the multi threading architecture more.

In turns, Oracle may reduce the number of process that it actually use to minimum, One process on behalf of all the other dedicated processes will work and drastically reduces the number of processes.

There will be a new parameter for this could be called threaded_executions or parallel_executions which can set to true, but yet to see.

Still need to understand the fundamental difference between MTS and this threaded executions, for that we may have to wait for manuals 🙁

-Thanks

Geek DBA

Script:- Check the resource dependencies in RAC Cluster

Sometimes You may require to check the dependencies for the resources for example to stop a ASM you will need to find what are the dependent resources in CRS or to change a vip what are the dependent resources associated with it to bring them down and perform your activity like chaning vip etc.

To do that,

 

#10g crs_stat -p | grep -v =$ | perl -nle 'if(/^NAME/){print}elsif(/^REQUIRED_RESOURCES/){print "t$_"}' #11g crsctl stat res -p | grep -v =$ | perl -nle 'if(/^NAME/){print}elsif(/DEPENDENCIES/){print "t$_"}' For example (11g): $ crsctl stat res -p | grep -v =$ | perl -nle 'if(/^NAME/){print}elsif(/DEPENDENCIES/){print "t$_"}' NAME=ora.DATA.dg START_DEPENDENCIES=hard(ora.asm) pullup(ora.asm) STOP_DEPENDENCIES=hard(intermediate:ora.asm) NAME=ora.FRA.dg START_DEPENDENCIES=hard(ora.asm) pullup(ora.asm) STOP_DEPENDENCIES=hard(intermediate:ora.asm)

Oracle Execution Plan: Common Join Methods explained

In Oracle execution plan, you often see Nested loops/Hash Joins/Merge Joins etc. These are called Join methods between row sources (tables/result sets of query).

You are can find more about Rowsource Join Methods here in the documentation

There are many join methods, out of all the following were common and generic

  • Nested loop join  
  • Hash join 
  • Sort merge join
  • Merge Join Cartesian

Nested Loop Join

Consider the following query

SQL> Select tab1.*, tab2.* from tabl, tab2 where tabl.col1=tab2.col2;

In terms of coding (c ) logic It is processed like:

For i in (select * from tab1) loop
For j in (select * from tab2 where col2=i.col1) loop
Display results;
End loop;
End loop;

The Steps involved in doing nested loop are:

a) Identify outer (driving) table

b) Assign inner (driven) table to outer table.

c) For every row of outer table, access the rows of inner table.

In execution plan it is seen like this:

NESTED LOOPS
outer_loop
inner_loop

 

--------------------------------------------------------------------------------
| Id | Operation 			| Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT 		| 	| 100 | 2200| 6 (0) | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID	| E 	| 25  | 225 | 1 (0) | 00:00:01 |
| 2 | NESTED LOOPS 		| 	| 100 | 2200| 6 (0) | 00:00:01 |
| 3 | TABLE ACCESS FULL 		| D 	| 4   | 52  | 3 (0) | 00:00:01 |
|* 4| INDEX RANGE SCAN 		| E_DEPT | 33  |     | 0 (0) | 00:00:01 |
--------------------------------------------------------------------------------

When optimizer uses nested loops?

Optimizer uses nested loop when we are joining tables containing small number of rows with an efficient driving condition. It is important to have an index on column of inner join table as this table is probed every time for a new value from outer table.

Optimizer may not use nested loop in case:

  • No of rows of both the table is quite high
  • Inner query always results in same set of records
  • The access path of inner table is independent of data coming from outer table.

Note: You will see more use of nested loop when using FIRST_ROWS optimizer mode as it works on model of showing instantaneous results to user as they are fetched. There is no need for selecting caching any data before it is returned to user. In case of hash join it is needed and is explained below.

Hash join

Hash joins are used when the joining large tables.The optimizer uses smaller of the 2 tables to build a hash table in memory and the scans the large tables and compares the hash value (of rows from large table) with this hash table to find the joined rows.

The algorithm of hash join is divided in two parts

  1. Build a in-memory hash table on smaller of the two tables.
  2. Probe this hash table with hash value for each row second table

In simpler terms it works like

Build phase

For each row RW1 in small (left/build) table loop

Calculate hash value on RW1 join key

Insert RW1 in appropriate hash bucket.

End loop;

Probe Phase

For each row RW2 in big (right/probe) table loop

Calculate the hash value on RW2 join key

For each row RW1 in hash table loop

If RW1 joins with RW2

Return RW1, RW2

End loop;

End loop;

When optimizer uses hash join?

Optimizer uses has join while joining big tables or big fraction of small tables.

Unlike nested loop, the output of hash join result is not instantaneous as hash joining is blocked on building up hash table.

Note: You may see more hash joins used with ALL_ROWS optimizer mode, because it works on model of showing results after all the rows of at least one of the tables are hashed in hash table.

Example:- For the example above I have no index and both table E and D are having large result set

-----------------------------------------------------------------------------------
| Id| Operation 	         | Name | Rows | Bytes	|TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT 	| 	| 250G| 5122G	| 	| 3968K(100)| 13:13:45 |
|* 1| HASH JOIN 	         | 	| 250G| 5122G	| 20M	| 3968K(100)| 13:13:45 |
| 2 | TABLE ACCESS FULL	| E 	| 1000K| 8789K	| 	| 2246 (3)  | 00:00:27 |
| 3 | TABLE ACCESS FULL	| D 	| 1000K| 12M	| 	| 2227 (2)  | 00:00:27 |
-----------------------------------------------------------------------------------

Sort merge join

Sort merge join is used to join two independent data sources. They perform better than nested loop when the volume of data is big in tables but not as good as hash joins in general.

They perform better than hash join when the join condition columns are already sorted or there is no sorting required.

The full operation is done in two parts:

  • Sort join operation

get first row RW1 from input1

get first row RW2 from input2.



  • Merge join operation

          while not at the end of either input loop

          if RW1 joins with RW2

          get next row R2 from input 2

          return (RW1, RW2)

          else if RW1 < style=""> get next row RW1 from input 1

          else

          get next row RW2 from input 2

         end loop

Note: If the data is already sorted, first step is avoided.

Important point to understand is, unlike nested loop where driven (inner) table is read as many number of times as the input from outer table, in sort merge join each of the tables involved are accessed at most once. So they prove to be better than nested loop when the data set is large.

When optimizer uses Sort merge join?

When the join condition is an inequality condition (like <, <=, >=). This is because hash join cannot be used for inequality conditions and if the data set is large, nested loop is definitely not an option.

If sorting is anyways required due to some other attribute (other than join) like “order by”, optimizer prefers sort merge join over hash join as it is cheaper.

Note: Sort merge join can be seen with both ALL_ROWS and FIRST_ROWS optimizer hint because it works on a model of first sorting both the data sources and then start returning the results. So if the data set is large and you have FIRST_ROWS as optimizer goal, optimizer may prefer sort merge join over nested loop because of large data. And if you have ALL_ROWS as optimizer goal and if any inequality condition is used the SQL, optimizer may use sort-merge join over hash join

Example:-

select e.ename,d.dname from e, d where e.deptno=d.deptno order by e.deptno;

-----------------------------------------------------------------------------------------
| Id | Operation 		     | Name 		| Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT 	     | 		| 2500K| 52M	| 167 (26)| 00:00:02 |
| 1 | MERGE JOIN 		     | 		| 2500K| 52M	| 167 (26)| 00:00:02 |
| 2 | TABLE ACCESS BYINDEX ROWID | E 	| 10000| 90000    | 102 (1) | 00:00:02 |
| 3 | INDEX FULL SCAN 	     | E_DEPTNO 	| 10000| 	         | 100 (0) | 00:00:02 |
|* 4 | SORT JOIN 		     | 		| 1000 | 13000 	| 25 (4)  | 00:00:01 |
| 5 | TABLE ACCESS FULL	     | D 		| 1000 | 13000 	| 24 (0)  | 00:00:01 |
-----------------------------------------------------------------------------------------

Merge Join Cartesian

A Cartesian join is used when one or more of the tables does not have any join conditions to any other tables in the statement. The optimizer joins every row from one data source with every row from the other data source, creating the Cartesian product of the two sets.

In some cases, a common filter condition between the two tables could be picked up by the optimizer as a possible join condition. This is even more dangerous, because the joins are not flagged in the execution plan as being a Cartesian product.

Cartesian joins generally result from poorly written SQL. has three tables in the FROM clause, but only one join condition joining the two tables.

Example:-

Cartesian Join with Distinct Clause
SELECT DISTINCT h.order_id, l.line_item_id, l.quantity
  FROM order_items l, orders h, order_items l2
 WHERE h.customer_id = :b1
   AND l.order_id = h.order_id;

Plan
-------------------------------------------------
SELECT STATEMENT
 SORT UNIQUE
  MERGE JOIN CARTESIAN
   NESTED LOOPS
    TABLE ACCESS BY INDEX ROWID ORDERS
     INDEX RANGE SCAN ORDER_ID
    TABLE ACCESS BY INDEX ROWID ORDER_ITEMS
     INDEX RANGE SCAN ORDER_ID
   SORT JOIN
    INDEX FAST FULL SCAN ORDER_ID

Here in above case Orders and Order Items is involved in Merge Join cartesian with tight nested loops and join condition between the third table is missing for example.

A = B , B = C must be there, for the third table Oracle automatically creates the condition C=A which is called transitivity retain “retain equi-join pred upon transitive equality pred generation”, Jonathan lewis.

Most of the cases when an merge join Cartesian is happening, below are the possible cases

Check Join Conditions (Most possible when an developer is writing new piece of code)

Start with the table joins. Check if there are any join conditions missing between the given tables in the query. As I said, Cartesian product is only possible when two tables have Many to Many join relation. In normal scenarios, the joins should be of the type: (a.primary_key = b.foreign_key) In most of the cases, adding proper join conditions will remove the Merge Join Cartesian from the plan.

Stale Statistics:- ( Most possible when a huge purge/load has happened to database and stats were stale)

The optimizer selects the best execution plan on the basis of the object statistics. If the statistics are stale, the plan might not be the optimal plan. Gather the statistics using DBMS_STATS package.

Optimizer Bug (_optimizer_transitivity_retain)

The issue with Optimizer regarding (_optimizer_transitivity_retain)

…..

There are other Join methods, for which I gather and add here soon.

-Thanks

Geek DBA