Anatomy of a SQL Tuning Session

Similar documents
Fallacies of the Cost Based Optimizer

D B M G Data Base and Data Mining Group of Politecnico di Torino

SQL Server Query Tuning

Oracle Database 11g: SQL Tuning Workshop

D B M G Data Base and Data Mining Group of Politecnico di Torino

An Oracle White Paper May The Oracle Optimizer Explain the Explain Plan

MOC 20461C: Querying Microsoft SQL Server. Course Overview

Oracle Database 11g: SQL Tuning Workshop Release 2

PERFORMANCE TUNING FOR PEOPLESOFT APPLICATIONS

Execution plans and tools

Oracle Database: SQL and PL/SQL Fundamentals

Informix SQL Performance Tuning Tips

PeopleSoft Query Training

Introduction to Querying & Reporting with SQL Server

Oracle Database: SQL and PL/SQL Fundamentals NEW

Execution Plans: The Secret to Query Tuning Success. MagicPASS January 2015

Oracle Database: SQL and PL/SQL Fundamentals

Advanced Oracle SQL Tuning

SQL Tuning Proven Methodologies

Oracle 11g PL/SQL training

MySQL for Beginners Ed 3

Oracle Database 10g: Program with PL/SQL

SQL Server for developers. murach's TRAINING & REFERENCE. Bryan Syverson. Mike Murach & Associates, Inc. Joel Murach

Introducing Microsoft SQL Server 2012 Getting Started with SQL Server Management Studio

Querying Microsoft SQL Server

FHE DEFINITIVE GUIDE. ^phihri^^lv JEFFREY GARBUS. Joe Celko. Alvin Chang. PLAMEN ratchev JONES & BARTLETT LEARN IN G. y ti rvrrtuttnrr i t i r

MTCache: Mid-Tier Database Caching for SQL Server

The Sins of SQL Programming that send the DB to Upgrade Purgatory Abel Macias. 1 Copyright 2011, Oracle and/or its affiliates. All rights reserved.

Execution Strategies for SQL Subqueries

Instant SQL Programming

DBMS / Business Intelligence, SQL Server

Querying Microsoft SQL Server 2012

Oracle SQL. Course Summary. Duration. Objectives

Advanced Query for Query Developers

Database Programming with PL/SQL: Learning Objectives

SQL SELECT Query: Intermediate

ICAB4136B Use structured query language to create database structures and manipulate data

Course ID#: W 35 Hrs. Course Content

Course 10774A: Querying Microsoft SQL Server 2012

Course 10774A: Querying Microsoft SQL Server 2012 Length: 5 Days Published: May 25, 2012 Language(s): English Audience(s): IT Professionals

Querying Microsoft SQL Server 20461C; 5 days

ORACLE 9I / 10G / 11G / PL/SQL COURSE CONTENT

How to Create Dashboards. Published

SQL Query Performance Tuning: Tips and Best Practices

Oracle White Paper June Optimizer with Oracle Database 12c

Query tuning by eliminating throwaway

Business Intelligence Extensions for SPARQL

Useful Business Analytics SQL operators and more Ajaykumar Gupte IBM

Course 20461C: Querying Microsoft SQL Server Duration: 35 hours

Saskatoon Business College Corporate Training Centre

Oracle Database 12c: Introduction to SQL Ed 1.1

University System of Georgia

MOC QUERYING MICROSOFT SQL SERVER

Efficient Data Access and Data Integration Using Information Objects Mica J. Block

SQL Server. 1. What is RDBMS?

Top 25+ DB2 SQL Tuning Tips for Developers. Presented by Tony Andrews, Themis Inc.

Querying Microsoft SQL Server 2012

Querying Microsoft SQL Server (20461) H8N61S

Creating Reports Crystal Clear

Duration Vendor Audience 5 Days Oracle End Users, Developers, Technical Consultants and Support Staff

Universe Best Practices Session Code: 806

AV-005: Administering and Implementing a Data Warehouse with SQL Server 2014

PEOPLESOFT VOUCHER TABLES IN THE DATA WAREHOUSE

In this session, we use the table ZZTELE with approx. 115,000 records for the examples. The primary key is defined on the columns NAME,VORNAME,STR

Querying Microsoft SQL Server Course M Day(s) 30:00 Hours

SQL Server Query Tuning

Chapter 9 Joining Data from Multiple Tables. Oracle 10g: SQL

Programming with SQL

Oracle Database 11g: New Features for Administrators 15-1

Oracle Database: Develop PL/SQL Program Units

Using AS/400 Database Monitor To Identify and Tune SQL Queries

Oracle Database: SQL and PL/SQL Fundamentals NEW

Module 1: Getting Started with Databases and Transact-SQL in SQL Server 2008

Performance Tuning for the JDBC TM API

Web Development using PHP (WD_PHP) Duration 1.5 months

Best Practices for DB2 on z/os Performance

Writing Queries Using Microsoft SQL Server 2008 Transact-SQL

Oracle 10g PL/SQL Training

Query Optimization in Oracle 12c Database In-Memory

ENHANCEMENTS TO SQL SERVER COLUMN STORES. Anuhya Mallempati #

Oracle EXAM - 1Z Oracle Database 11g Release 2: SQL Tuning. Buy Full Product.

SQL Performance Hero and OMG Method vs the Anti-patterns. Jeff Jacobs Jeffrey Jacobs & Associates jmjacobs@jeffreyjacobs.com

Oracle Database 11 g Performance Tuning. Recipes. Sam R. Alapati Darl Kuhn Bill Padfield. Apress*

LearnFromGuru Polish your knowledge

... IBM AIX with Oracle Database performance: a beginner s guide

1Z0-117 Oracle Database 11g Release 2: SQL Tuning. Oracle

TWO TYPES OF HISTOGRAMS

The Database is Slow

Querying Microsoft SQL Server Querying Microsoft SQL Server D. Course 10774A: Course Det ails. Co urse Outline

Safe Harbor Statement

Business Intelligence Tutorial: Introduction to the Data Warehouse Center

Optimizing Your Database Performance the Easy Way

Oracle Database Security

PATROL From a Database Administrator s Perspective

SQL Performance for a Big Data 22 Billion row data warehouse

Would-be system and database administrators. PREREQUISITES: At least 6 months experience with a Windows operating system.

Writing Queries Using Microsoft SQL Server 2008 Transact-SQL

Database Application Developer Tools Using Static Analysis and Dynamic Profiling

Transcription:

Anatomy of a SQL Tuning Session Wolfgang Breitling www.centrexcc.com Copyright 2009 Centrex Consulting Corporation. Personal use of this material is permitted. However, permission to reprint/republish this material for advertising and promotional purposes or for creating new collective works for resale or redistribution to servers or lists, or to reuse any copyrighted component of this work in other works must be obtained from Centrex Consulting.

Who am I Independent consultant since 1996 specializing in Oracle and Peoplesoft setup, administration, and performance tuning Member of the Oaktable Network 30+ years in database management DL/1, IMS, ADABAS, SQL/DS, DB2, Oracle Oracle since 1993 (7.0.12) OCP certified DBA - 7, 8, 8i, 9i Mathematics major from University of Stuttgart 2

Using the R-Method in SQL Tuning Logical extension of TCF with the availability of v$sql_plan_statistics in 9i and up At the session level Set statistics_level = all Set _rowsource_execution_statistics = true At the sql level Use GATHER_PLAN_STATISTICS hint 3

The SQL SELECT BUSINESS_UNIT, VOUCHER_ID, BANK_SETID, BANK_CD, BANK_ACCT_KEY, NAME1, INVOICE_ID, GROSS_AMT, TXN_CURRENCY_CD, TO_CHAR(SCHEDULED_PAY_DT,'YYYY-MM-DD'), PYMNT_HOLD, PYMNT_HOLD_REASON, APPR_STATUS, EXPRESS_PAY, VENDOR_ID FROM PS_VCHR_HLD_VW A WHERE '12345' IN ( SELECT X.OPERATING_UNIT FROM PS_DISTRIB_LINE X WHERE A.VOUCHER_ID = X.VOUCHER_ID AND A.BUSINESS_UNIT = X.BUSINESS_UNIT) 4

Baseline Id Operation Name A-Time ---------------------------------------------------------------- 1 NESTED LOOPS 08:46.81 2 NESTED LOOPS OUTER 07:29.40 3 NESTED LOOPS 04:52.31 4 TABLE ACCESS BY INDEX ROWID PS_PYMNT_VCHR_XREF 04:20.48 5 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 09.55 6 TABLE ACCESS BY INDEX ROWID PS_VENDOR 30.75 7 INDEX UNIQUE SCAN PS_VENDOR 06.95 8 TABLE ACCESS BY INDEX ROWID PS_VCH_APPR_DTL 02:35.22 9 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 46.77 10 TABLE ACCESS BY INDEX ROWID PS_VOUCHER 01:16.72 11 INDEX UNIQUE SCAN PS_VOUCHER 01:15.33 12 INDEX RANGE SCAN PSCDISTRIB_LINE 03.64 11 Access= "A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT" AND "A"."VOUCHER_ID"="B"."VOUCHER_ID 12 Access= "X"."OPERATING_UNIT"='12345' AND "X"."BUSINESS_UNIT"=:B1 AND "X"."VOUCHER_ID"=:B2 5

Baseline Id Operation Name Starts Rows --- ------------------------- ------------------- ------- -------- 1 NESTED LOOPS 1 15 2 NESTED LOOPS OUTER 1 284,029 3 NESTED LOOPS 1 284,029 4 TABLE ACCESS BY INDEX PS_PYMNT_VCHR_XREF 1 284,029 5 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 1 476,577 6 TABLE ACCESS BY INDEX PS_VENDOR 284,029 284,029 7 INDEX UNIQUE SCAN PS_VENDOR 284,029 284,029 8 TABLE ACCESS BY INDEX PS_VCH_APPR_DTL 284,029 252,931 9 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 284,029 252,931 10 TABLE ACCESS BY INDEX PS_VOUCHER 284,029 15 11 INDEX UNIQUE SCAN PS_VOUCHER 284,029 15 12 INDEX RANGE SCAN PSCDISTRIB_LINE 284,014 15 6

Baseline Id Operation Name Starts Rows --- ------------------------- ------------------- ------- -------- 1 NESTED LOOPS 1 15 2 NESTED LOOPS OUTER 1 284,029 3 NESTED LOOPS 1 284,029 4 TABLE ACCESS BY INDEX PS_PYMNT_VCHR_XREF 1 284,029 5 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 1 476,577 6 TABLE ACCESS BY INDEX PS_VENDOR 284,029 284,029 7 INDEX UNIQUE SCAN PS_VENDOR 284,029 284,029 8 TABLE ACCESS BY INDEX PS_VCH_APPR_DTL 284,029 252,931 9 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 284,029 252,931 10 TABLE ACCESS BY INDEX PS_VOUCHER 284,029 15 11 INDEX UNIQUE SCAN PS_VOUCHER 284,029 15 12 INDEX RANGE SCAN PSCDISTRIB_LINE 284,014 15 7

Using Scalar Subquery SELECT A.BUSINESS_UNIT, A.VOUCHER_ID, C.NAME1, D.EXPRESS_PAY, B.BANK_SETID, B.BANK_CD, B.BANK_ACCT_KEY FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B, PS_VENDOR C, PS_VCH_APPR_DTL D WHERE A.BUSINESS_UNIT = B.BUSINESS_UNIT AND A.VOUCHER_ID = B.VOUCHER_ID AND C.SETID = B.REMIT_SETID AND C.VENDOR_ID = B.REMIT_VENDOR AND B.BUSINESS_UNIT = D.BUSINESS_UNIT(+) AND B.VOUCHER_ID = D.VOUCHER_ID(+) 8

Using Scalar Subquery SELECT A.BUSINESS_UNIT, A.VOUCHER_ID, C.NAME1, (select D.EXPRESS_PAY D.EXPRESS_PAY, PS_VCH_APPR_DTL from PS_VCH_APPR_DTL D D where AND B.BUSINESS_UNIT = = D.BUSINESS_UNIT(+) AND B.VOUCHER_ID = = D.VOUCHER_ID) D.VOUCHER_ID(+) EXPRESS_PAY, B.BANK_SETID, B.BANK_CD, B.BANK_ACCT_KEY FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B, PS_VENDOR C WHERE A.BUSINESS_UNIT = B.BUSINESS_UNIT AND A.VOUCHER_ID = B.VOUCHER_ID AND C.SETID = B.REMIT_SETID AND C.VENDOR_ID = B.REMIT_VENDOR 9

Using Scalar Subquery SELECT A.BUSINESS_UNIT, A.VOUCHER_ID, (select C.NAME1 from PS_VENDOR C where C.SETID = B.REMIT_SETID AND C.VENDOR_ID = B.REMIT_VENDOR) NAME1, (select D.EXPRESS_PAY from PS_VCH_APPR_DTL D where B.BUSINESS_UNIT = D.BUSINESS_UNIT AND B.VOUCHER_ID = D.VOUCHER_ID) EXPRESS_PAY, B.BANK_SETID, B.BANK_CD, B.BANK_ACCT_KEY FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B WHERE A.BUSINESS_UNIT = B.BUSINESS_UNIT AND A.VOUCHER_ID = B.VOUCHER_ID 10

Subquery Factoring* with PS_VCHR_HLD_VW AS ( SELECT A.BUSINESS_UNIT, A.VOUCHER_ID FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B ) SELECT BUSINESS_UNIT, VOUCHER_ID, BANK_SETID, BANK_CD, BANK_ACCT_KEY, NAME1, INVOICE_ID, GROSS_AMT, TXN_CURRENCY_CD, TO_CHAR(SCHEDULED_PAY_DT,'YYYY-MM-DD'), PYMNT_HOLD, PYMNT_HOLD_REASON, APPR_STATUS, EXPRESS_PAY, VENDOR_ID FROM PS_VCHR_HLD_VW F WHERE '12345' IN ( SELECT X.OPERATING_UNIT FROM PS_DISTRIB_LINE X WHERE F.VOUCHER_ID = X.VOUCHER_ID AND F.BUSINESS_UNIT = X.BUSINESS_UNIT) * aka Common Table Expression ( CTE ) 11

Plan with Scalar Subqueries Id Operation Name A-Time ---- ---------------------------- ------------------- -------- 1 TABLE ACCESS BY INDEX ROWID PS_VENDOR 00.01 2 INDEX UNIQUE SCAN PS_VENDOR 00.01 3 TABLE ACCESS BY INDEX ROWID PS_VCH_APPR_DTL 00.01 4 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 00.01 5 NESTED LOOPS 07:55.59 6 TABLE ACCESS BY INDEX ROWID PS_PYMNT_VCHR_XREF 06:14.85 7 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 13.86 8 TABLE ACCESS BY INDEX ROWID PS_VOUCHER 01:39.57 9 INDEX UNIQUE SCAN PS_VOUCHER 01:37.19 10 INDEX RANGE SCAN PSCDISTRIB_LINE 05.91 9 Access= "A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT" AND "A"."VOUCHER_ID"="B"."VOUCHER_ID" 9 Filter= IS NOT NULL 10 Access= "X"."OPERATING_UNIT"= '12345' AND "X"."BUSINESS_UNIT"=:B1 AND "X"."VOUCHER_ID"=:B2 12

Convert in SQ to Join with PS_VCHR_HLD_VW AS ( SELECT A.BUSINESS_UNIT, A.VOUCHER_ID FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B ) SELECT BUSINESS_UNIT, VOUCHER_ID, BANK_SETID, BANK_CD, BANK_ACCT_KEY, NAME1, INVOICE_ID, GROSS_AMT, TXN_CURRENCY_CD, TO_CHAR(SCHEDULED_PAY_DT,'YYYY-MM-DD'), PYMNT_HOLD, PYMNT_HOLD_REASON, APPR_STATUS, EXPRESS_PAY, VENDOR_ID FROM MI_VCHR_HLD_VW F, PS_DISTRIB_LINE X WHERE X.OPERATING_UNIT = '12345' AND F.VOUCHER_ID = X.VOUCHER_ID AND F.BUSINESS_UNIT = X.BUSINESS_UNIT 13

Plan after Unnest Id Operation Name A-Time --- ------------------------------ ------------------- -------- 1 TABLE ACCESS BY INDEX ROWID PS_VENDOR 00.03 2 INDEX UNIQUE SCAN PS_VENDOR 00.02 3 TABLE ACCESS BY INDEX ROWID PS_VCH_APPR_DTL 00.03 4 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 00.01 5 NESTED LOOPS 01:37.64 6 NESTED LOOPS 01:37.55 7 TABLE ACCESS BY INDEX ROWID PS_PYMNT_VCHR_XREF 22.78 8 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 03.29 9 TABLE ACCESS BY INDEX ROWID PS_VOUCHER 01:14.30 10 INDEX UNIQUE SCAN PS_VOUCHER 14.23 11 INDEX RANGE SCAN PSCDISTRIB_LINE 00.09 8 - access("b"."pymnt_id"=' ') filter("b"."pymnt_id"=' ') 10 - access("a"."business_unit"="b"."business_unit" AND "A"."VOUCHER_ID"="B"."VOUCHER_ID") 11 - access("x"."operating_unit"='12345' AND "A"."BUSINESS_UNIT"="X"."BUSINESS_UNIT" AND "A"."VOUCHER_ID"="X"."VOUCHER_ID") 14

Plan after Unnest Id Operation Name Starts Rows --- ------------------------ ------------------- -------- -------- 1 TABLE ACCESS BY INDEX PS_VENDOR 15 15 2 INDEX UNIQUE SCAN PS_VENDOR 15 15 3 TABLE ACCESS BY INDEX PS_VCH_APPR_DTL 21 21 4 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 21 21 5 NESTED LOOPS 1 24 6 NESTED LOOPS 1 10,099 7 TABLE ACCESS BY INDEX PS_PYMNT_VCHR_XREF 1 284,029 8 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 1 476,577 9 TABLE ACCESS BY INDEX PS_VOUCHER 284,029 10,099 10 INDEX UNIQUE SCAN PS_VOUCHER 284,029 252,931 11 INDEX RANGE SCAN PSCDISTRIB_LINE 10,099 24 15

Transitive Closure with PS_VCHR_HLD_VW AS ( SELECT A.BUSINESS_UNIT, B.BUSINESS_UNIT, B.VOUCHER_ID A.VOUCHER_ID FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B ) SELECT BUSINESS_UNIT, VOUCHER_ID, BANK_SETID, BANK_CD, BANK_ACCT_KEY, NAME1, INVOICE_ID, GROSS_AMT, TXN_CURRENCY_CD, TO_CHAR(SCHEDULED_PAY_DT,'YYYY-MM-DD'), PYMNT_HOLD, PYMNT_HOLD_REASON, APPR_STATUS, EXPRESS_PAY, VENDOR_ID FROM MI_VCHR_HLD_VW F, PS_DISTRIB_LINE X WHERE X.OPERATING_UNIT = '39002' AND F.VOUCHER_ID = X.VOUCHER_ID AND F.BUSINESS_UNIT = X.BUSINESS_UNIT 16

Plan after Transitive Closure Id Operation Name A-Time --- ------------------------------ ------------------- -------- 1 TABLE ACCESS BY INDEX ROWID PS_VENDOR 00:00.07 2 INDEX UNIQUE SCAN PS_VENDOR 00:00.05 3 TABLE ACCESS BY INDEX ROWID PS_MI_VCH_APPR_DTL 00:00.09 4 INDEX UNIQUE SCAN PS_MI_VCH_APPR_DTL 00:00.02 5 NESTED LOOPS 00:33.85 6 NESTED LOOPS 00:33.82 7 TABLE ACCESS BY INDEX ROWID PS_PYMNT_VCHR_XREF 00:32.07 8 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 00:04.10 9 INDEX RANGE SCAN PSCDISTRIB_LINE 00:01.46 10 TABLE ACCESS BY INDEX ROWID PS_VOUCHER 00:00.03 11 INDEX UNIQUE SCAN PS_VOUCHER 00:00.01 8 - access("b"."pymnt_id"=' ') filter("b"."pymnt_id"=' ') 9 - access("x"."operating_unit"='12345' AND "B"."BUSINESS_UNIT"="X"."BUSINESS_UNIT" AND "B"."VOUCHER_ID"="X"."VOUCHER_ID") 11 - access("a"."business_unit"="b"."business_unit" AND "A"."VOUCHER_ID"="B"."VOUCHER_ID") 17

10g Outline dbms_xplan.display[_cursor](,,'outline [other options]') Outline Data /*+ BEGIN_OUTLINE_DATA IGNORE_OPTIM_EMBEDDED_HINTS ALL_ROWS INDEX_RS_ASC(@"SEL$16C51A37" INDEX_SS(@"SEL$16C51A37" "B"@"SEL$1" "PSBPYMNT_VCHR_XREF") "PS_PYMNT_VCHR_XREF") INDEX_RS_ASC(@"SEL$16C51A37" "A"@"SEL$1" "PS_VOUCHER") INDEX(@"SEL$16C51A37" "X"@"SEL$4" "PSCDISTRIB_LINE") LEADING(@"SEL$16C51A37" "B"@"SEL$1" "X"@"SEL$4" "A"@"SEL$1" "B"@"SEL$1" "X"@"SEL$4") "A"@"SEL$1") USE_NL(@"SEL$16C51A37" "A"@"SEL$1") USE_NL(@"SEL$16C51A37" "X"@"SEL$4") INDEX_RS_ASC(@"SEL$3" "D"@"SEL$3" "PS_VCH_APPR_DTL") INDEX_RS_ASC(@"SEL$2" "C"@"SEL$2" "PS_VENDOR") END_OUTLINE_DATA */ 18

Query Block Names SELECT FROM VCHR_HLD_VW F, PS_DISTRIB_LINE X WHERE F.VOUCHER_ID = X.VOUCHER_ID AND F.BUSINESS_UNIT = X.BUSINESS_UNIT AND X.OPERATING_UNIT = '12345' SELECT A.BUSINESS_UNIT, A.VOUCHER_ID, (select C.NAME1 from PS_VENDOR C where C.SETID = B.REMIT_SETID AND C.VENDOR_ID = B.REMIT_VENDOR) NAME1, (select D.EXPRESS_PAY from PS_VCH_APPR_DTL D where B.BUSINESS_UNIT = D.BUSINESS_UNIT AND B.VOUCHER_ID = D.VOUCHER_ID) EXPRESS_PAY, B.BANK_SETID, B.BANK_CD, B.BANK_ACCT_KEY FROM PS_VOUCHER A, PS_PYMNT_VCHR_XREF B WHERE A.BUSINESS_UNIT = B.BUSINESS_UNIT AND A.VOUCHER_ID = B.VOUCHER_ID Query Block Name / Object Alias 1 - SEL$2 / C@SEL$2 2 - SEL$2 / C@SEL$2 3 - SEL$3 / D@SEL$3 4 - SEL$3 / D@SEL$3 5 - SEL$16C51A37 7 - SEL$16C51A37 / X@SEL$4 8 - SEL$16C51A37 / B@SEL$1 9 - SEL$16C51A37 / B@SEL$1 10 - SEL$16C51A37 / A@SEL$1 11 - SEL$16C51A37 / A@SEL$1 19

Add Hints with PS_VCHR_HLD_VW AS () SELECT /*+ INDEX(@SEL$16C51A37 X@SEL$4 PSCDISTRIB_LINE) INDEX_RS_ASC(@SEL$16C51A37 B@SEL$1 PS_PYMNT_VCHR_XREF) INDEX_RS_ASC(@SEL$16C51A37 A@SEL$1 PS_VOUCHER) LEADING(@SEL$16C51A37 X@SEL$4 B@SEL$1 A@SEL$1) USE_NL(@SEL$16C51A37 B@SEL$1) USE_NL(@SEL$16C51A37 A@SEL$1) INDEX_RS_ASC(@SEL$3 D@SEL$3 PS_VCH_APPR_DTL) INDEX_RS_ASC(@SEL$2 C@SEL$2 PS_VENDOR) */ BUSINESS_UNIT, VOUCHER_ID, BANK_SETID, BANK_CD, BANK_ACCT_KEY, NAME1, INVOICE_ID, GROSS_AMT, TXN_CURRENCY_CD, TO_CHAR(SCHEDULED_PAY_DT,'YYYY-MM-DD'), PYMNT_HOLD, PYMNT_HOLD_REASON, APPR_STATUS, EXPRESS_PAY, VENDOR_ID FROM MI_VCHR_HLD_VW F, PS_DISTRIB_LINE X WHERE X.OPERATING_UNIT = '12345' AND F.VOUCHER_ID = X.VOUCHER_ID AND F.BUSINESS_UNIT = X.BUSINESS_UNIT 20

Plan with Hints Id Operation Name A-Time --- ------------------------------ ------------------ --------- 1 TABLE ACCESS BY INDEX ROWID PS_VENDOR 00.01 2 INDEX UNIQUE SCAN PS_VENDOR 00.01 3 TABLE ACCESS BY INDEX ROWID PS_VCH_APPR_DTL 00.01 4 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 00.01 5 NESTED LOOPS 00.01 6 NESTED LOOPS 00.01 7 INDEX RANGE SCAN PSCDISTRIB_LINE 00.01 8 TABLE ACCESS BY INDEX ROWID PS_PYMNT_VCHR_XREF 00.01 9 INDEX RANGE SCAN PS_PYMNT_VCHR_XREF 00.01 10 TABLE ACCESS BY INDEX ROWID PS_VOUCHER 00.01 11 INDEX UNIQUE SCAN PS_VOUCHER 00.01 7 - access("x"."operating_unit"='12345') 8 - filter(("b"."pymnt_id"=' ' AND )) 9 - access("b"."business_unit"="x"."business_unit" AND "B"."VOUCHER_ID"="X"."VOUCHER_ID") 11 - access("a"."business_unit"="b"."business_unit" AND "A"."VOUCHER_ID"="B"."VOUCHER_ID") 21

Plan with Hints Id Operation Name Starts Rows --- ------------------------- ------------------ ------- ------ 1 TABLE ACCESS BY INDEX PS_VENDOR 15 15 2 INDEX UNIQUE SCAN PS_VENDOR 15 15 3 TABLE ACCESS BY INDEX PS_VCH_APPR_DTL 21 21 4 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 21 21 5 NESTED LOOPS 1 24 6 NESTED LOOPS 1 28 7 INDEX RANGE SCAN PSCDISTRIB_LINE 1 395 8 TABLE ACCESS BY INDEX PS_PYMNT_VCHR_XREF 395 28 9 INDEX RANGE SCAN PS_PYMNT_VCHR_XREF 395 395 10 TABLE ACCESS BY INDEX PS_VOUCHER 28 24 11 INDEX UNIQUE SCAN PS_VOUCHER 28 28 22

Compare to Baseline (~9 min) Id Operation Name Starts Rows --- ------------------------- ------------------- ------- -------- 1 NESTED LOOPS 1 15 2 NESTED LOOPS OUTER 1 284,029 3 NESTED LOOPS 1 284,029 4 TABLE ACCESS BY INDEX PS_PYMNT_VCHR_XREF 1 284,029 5 INDEX SKIP SCAN PSBPYMNT_VCHR_XREF 1 476,577 6 TABLE ACCESS BY INDEX PS_VENDOR 284,029 284,029 7 INDEX UNIQUE SCAN PS_VENDOR 284,029 284,029 8 TABLE ACCESS BY INDEX PS_VCH_APPR_DTL 284,029 252,931 9 INDEX UNIQUE SCAN PS_VCH_APPR_DTL 284,029 252,931 10 TABLE ACCESS BY INDEX PS_VOUCHER 284,029 15 11 INDEX UNIQUE SCAN PS_VOUCHER 284,029 15 12 INDEX RANGE SCAN PSCDISTRIB_LINE 284,014 15 23

Techniques Used Scalar Subqueries Subquery Factoring Transitive Closure Un-nesting Convert in Subquery to Join Hints 24

Information Used dbms_xplan.display_cursor Rowsource Timing Information Rowsource Starts and Actual Rows Access and Filter Predicates Outline Index Definitions Application Knowledge 25

Wolfgang Breitling breitliw@centrexcc.com Centrex Consulting Corp. www.centrexcc.com