Académique Documents
Professionnel Documents
Culture Documents
Abstract:
The paper covers a range of methods for improving the performance of Peoplesoft HR
applications on an Oracle database. It includes information on implementing the cost-based
optimizer along with a variety of indexing strategies and other information. The paper presents
innovative ways to enhance the performance of Peoplesoft HR applications, encompassing Batch,
OLTP and DSS environments. The authors also share documented performance enhancements
and benchmark information.
The paper is a team effort of two Oracle Database Administrators who met on-line soon after the
formation of the Peoplesoft-SIG of the IOUG-A. After the group started, they began to exchange
notes and information regarding Peoplesoft HR on Oracle. The database environments at both
sites are somewhat similar - in terms of the size of the database and organizational size, however
the workload and on each database environment is as different as the business needs which drive
the use of the application. The similarity of the techniques used in both environments, mainly
implementation of the Cost-Based Optimizer, was striking. The authors decided to share their
experiences with the Oracle community in the form of this publication.
Table of Contents
1
Introduction:............................................................................................................................4
4.2
4.2.1
4.2.2
Collecting Statistics:................................................................................................12
4.2.3
4.2.4
OnLine Access.......................................................................................................................13
5.1
General Information.......................................................................................................13
5.2
Case Study......................................................................................................................14
Batch Jobs.............................................................................................................................14
6.1
General Information.......................................................................................................14
6.2
6.2.1
6.3
7
Actions taken...........................................................................................................15
Final Results...................................................................................................................30
General Information.......................................................................................................30
7.2
7.3
Case Studies...................................................................................................................31
7.4
Final Results...................................................................................................................44
Appendix A: Scripts..............................................................................................................45
10
11
12
Table of Figures
Figure 1: A simple query joining three-tables and the RBO execution plan....................................7
Figure 2: Query with table order switched in the FROM clause for RBO......................................8
Figure 3: Query with cost-based optimizer.....................................................................................9
Figure 4: Query with table order switched in the FROM clause for CBO......................................9
Figure 5: Panel Access Speeds......................................................................................................14
Figure 6: Calc Query....................................................................................................................15
Figure 7: Calc Tables....................................................................................................................16
Figure 8: Initial Explain................................................................................................................17
Figure 9: PS_JOB1_NDX.............................................................................................................19
Figure 10: Bit Map Explain..........................................................................................................19
Figure 11: TKPROF......................................................................................................................22
Figure 12: PS_PAY_LINE1_NDX................................................................................................27
Figure 13: Final Tkprof for CALC................................................................................................27
Figure 14: Run-time comparison of 12 queries between Rule-Based Optimizer and Cost-Based
Optimizer...............................................................................................................................32
Figure 15:PS_PERSONAL_SRCH View.....................................................................................32
Figure 16: Details of Query2 (without hinted PS_PERSONAL_SRCH_Q View)........................32
Figure 17: Details of Query2 (with hinted PS_PERSONAL_SRCH_Q view)..............................39
1 Introduction:
Access to Peoplesoft HR Applications (HR, Benefits, Payroll, Self-Service etc.) on an Oracle
Database can be classified into three major categories: Batch Jobs (Payrolls, SQR's/Reports),
Online Access (OLTP - Panel Users) and Decision Support (PSQUERY and custom reports.) The
following sections present tuning studies and suggestions for each of the categories including test
results, case studies and associated data. Information about Batch Jobs and Online Access was
provided by James Strange. Information about DSS systems was provided by Raman Batra.
table. Finally, the scripts makeExplain.sql and exp.sql can be used to obtain the execution plans
for the SQL associated with a particular sid.
No matter what method used to monitor your system, you must be able to identify problem areas,
especially during payroll batch runs. Thomas (1988)1 has published an excellent roadmap for
identifying bottlenecks and tuning your Oracle server and database environments for Peoplesoft
Applications. In particular the techniques used to identify and isolate performance bottlenecks
are definitely worth reading. Peoplesoft Corporation seems to have increased the number of bind
variables with release 7.x of Peoplesoft as compared to release 6.x, so some time is saved parsing
SQL statements with different variable values, which helps performance somewhat. In addition,
the bind variables help reduce contention in the buffer cache.
2. Rule Based Optimizer (RBO): The Rule-Based Optimizer is the "old faithful" way of Oracle
processing, and a very predictable way of choosing a query plan. It works exactly the same way
even if a table has 10 rows or 10 million rows, which can be a blessing or a curse, depending
upon several factors, most importantly your data distribution. The RBO is not aware of the
distribution of values in a data-segment and does not take advantage of histograms, which track
the dispersion of values in a data and/or index segment. The RBO uses a predefined set of rules
based on precedence logic to figure out what access path to use. It is driven by about 15
precedence rankings (with single row access by rowid at the very top and full table scan right at
the bottom of the rankings. Several good tuning publications 2,3,4 detail these precedence
rankings. The rule-based optimizer chooses an access path based on:
The WHERE clause of the SQL statements and the order of the table-names in the FROM clause
help the RBO to determine possible access paths. The optimizer then chooses the highest ranked
access path. Access by index is always ranked higher than tablescans. As a result, the optimizer
will always prefer an access path which uses an index. In some cases that approach can be a
problem. Sometimes a full table scan may execute faster than access by index. The usual
solution for a bad plan with the RBO is to place hints in the query, which will direct the optimizer
to a better plan. Unfortunately, that solution is frequently not available, and most ERP systems,
including Peoplesoft, do not encourage you to change the code even where possible. In the case
of Peoplesofts PSQUERY tool, it is effectively impossible to add hints to queries.
If you do not have a separate environment for decision support, you could have a few "queries
from hell" consuming most of your system resources and dragging down the online and payroll
processes. It is mostly in decision support and OLTP where you will find the biggest limitations
of the RBO. As Jim found out with online access, the improvements were dramatic after the RBO
was replaced with the CBO.
In the RBO, the last table in the FROM clause acts as a driving table, all things being equal.
In the CBO, according to published literature, the first table in the FROM clause acts as a
driving table, unless the optimizer determines a different plan will perform better. This again
depends upon how the tables are joined and if the join results in a table scan, unique index
scan or index range scan. We found the Cost-Based Optimizer generated the same execution
plan, no matter what table order was used in the FROM clause. The following figures
illustrate the effect of changing the table order for the RBO.
Theexecutionplanforthiswiththerulebasedoptimizeris:
QueryPlan
SELECTSTATEMENTCost=
NESTEDLOOPS
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
TABLEACCESSBYINDEXROWIDPS_DIRECT_DEPOSIT
INDEXRANGESCANPS_DIRECT_DEPOSIT
In the above plan the first table processed is PS_PERSONAL_DATA, followed by PS_JOB, the
results are put into a nested loop and the result set is matched with data from the third table -
PS_DIRECT_DEPOSIT. The driving table, or the table first processed will always be
PS_PERSONAL_DATA because of the clause a.emplid='99999'.
Figure 2: Query with table order switched in the FROM clause for
RBO
selecta.name,a.phone,b.empl_status,b.effdt,c.empl_rcd#,c.eff_status
fromsysadm.ps_jobb,
sysadm.ps_direct_depositc,
sysadm.ps_personal_dataa
wherea.emplid='99999'
andc.emplid=a.emplid
anda.emplid=b.emplid
andc.emplid=a.emplid
ExecutionPlanfortheabovequery:
QueryPlan
SELECTSTATEMENTCost=
NESTEDLOOPS
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_DIRECT_DEPOSIT
INDEXRANGESCANPS_DIRECT_DEPOSIT
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
QueryPlan
SELECTSTATEMENTCost=9
NESTEDLOOPS
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_DIRECT_DEPOSIT
INDEXRANGESCANPS_DIRECT_DEPOSIT
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
Figure 4: Query with table order switched in the FROM clause for
CBO
selecta.name,a.phone,b.empl_status,b.effdt,c.empl_rcd#,c.eff_status
fromsysadm.ps_jobb,
sysadm.ps_direct_depositc,
sysadm.ps_personal_dataa
wherea.emplid='99999'
andc.emplid=a.emplid
anda.emplid=b.emplid
andc.emplid=a.emplid
QueryPlan
SELECTSTATEMENTCost=9
NESTEDLOOPS
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_DIRECT_DEPOSIT
INDEXRANGESCANPS_DIRECT_DEPOSIT
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
This behavior can be both a blessing and a curse. When dealing with Decision Support
Environments, the person writing the queries is intent on getting the business logic and typically
does not want be concerned about the order of tables in a query. In fact, quite a few queries are
constantly changed as managers or end-users add requirements. This frequently results in
complicated FROM and AND clauses, and ever growing numbers of columns in the SELECT
statement. In such a case, the CBO frees the developer from worrying about the table order. This
also holds true for adhoc tools such as PSQUERY. Unfortunately, the CBO can hurt
performance in some circumstances. If it does not have the right statistics or chooses a bad
execution path, performance can be very bad.
In Ramans system, which is a mixed OLTP, Decision Support and Batch environment, frequently
they came across "queries from hell" which would take hours, even days to complete. Simply reordering the tables in the join made a tremendous difference under the RBO.
Comparing the two optimizer modes is somewhat like comparing an automatic transmission
(CBO) to a manual transmission (RBO). The RBO, maintained by Oracle Corporation for
backward compatibility, gives developers a lot of control over the way SQL statements execute.
However, in most ERP applications, and Peoplesoft is no exception, it sometimes is impossible to
modify SQL, so the optimizer to make intelligent selections to satisfy rather generic queries.
That is where the CBO can be of crucial benefit.
they advise using RULES? Peoplesoft is not in the database business. They operate on a number
of platforms and have little desire to keep up with changes to Oracle. Plus, as mentioned before,
the early versions of the CBO were justifiably scorned.
Starting with Oracle 7.3.4 things have changed. Our tests have indicated that significant
performance gains may be achieved by going against the advice of Peoplesoft and using the CBO
set to first_rows mode. However, the unfortunate truth is that while the CBO has great potential
for improving performance, it can also take a good deal of effort to make it work well for your
environment. If your shop has a number of custom reports or jobs tuned to work with the RBO,
changing to CBO may in fact hurt the performance of those jobs.
As an example, Jim implemented cost based optimization at his employer. They experienced
increased performance for nearly all online access. Panels, which formerly required 20+ seconds
would appear in 2 or 3 seconds using the cost, based optimizer. This was greeted by a great deal
of enthusiasm by the customers. However, when the batch cycle ran for payroll the party
ended. Payroll was extremely slow. So, they restarted the database in order to switch back to
rules. The payroll then finished in a reasonable amount of time.
Eventually Jim was able to identify and cure the problems with the batch jobs. Their shop now
runs in CBO 24 hours a day. However, this serves to illustrate that implementing the CBO can be
a challenge, initially requiring significant work from the DBA.
11
ALL_ROWS: ALL_ROWS is better for batch situations where you want the batch job to
complete, but you don't necessarily want to monitor data being processed. You may find that
the percentage of hash-joins increases as compared to nested loops.
In our experience, we found FIRST_ROWS to give superior results to ALL_ROWS for
Peoplesoft applications.
2. Session Level - Within each session, you can change the optimizer mode, as long as you have
the ALTER SESSION privilege. In Peoplesoft, it is very hard use this option with online
panels. It is relatively easy to insert an ALTER SESSION in the SQR's. Alternatively you can
change the optimizer mode in the initialization file of the SQR (Ask Dustan/Kendall).
However, either of these approaches can lead to a lot of customizations in SQRs, which
makes it a questionable course of action.
When starting to implement the CBO, one approach is to set the default mode for the instance
as FIRST_ROWS and use RULE for the batch jobs via the ALTER SESSION command until
you have tuned them.
An example would be:
SQL>ALTER SESSION SET OPTIMIZER_GOAL=RULE;
3. Code Level (using Hints) - In a SQL statement, you can give hints. Hints tell the optimizer
what access path you want it to use. You can force full-table scans, or force the statement to
use a specific index. Unless you use the RULE hint, almost every hint uses cost-based
optimization.
The optimum way would be to set the init.ora to a particular mode and then let every process online, batch and decision support to default to that optimizer mode. However, as you transition
to the CBO, you may use some or all of the above methods to change your optimizer settings.
12
3. Execute DBMS_UTILITY.ANALYZE_SCHEMA('SYSADM','COMPUTE',NULL,30);
This Oracle supplied package will analyze the entire schema, tables and indexes both, and
you can specify the method (compute or estimate).
Depending upon the volatility of the data, you may increase the sample to 100 percent or to a
specified number of rows, in most cases 25-30% sample is enough for the optimizer to work
accurately. Computing statistics is CPU and memory intensive and will take a fair amount of
temp space, so it is recommended this be performed during off-hours. You will need statistics for
tables and indexes. Collecting statistics for tables will also collect index statistics, however if you
rebuild an index or create a new one, you will need to collect statistics for the rebuilt/new/altered
indexes.
5 OnLine Access
5.1 General Information
When the cost based optimizer was implemented at Jims employer, there was a significant
improvement in online response time. Screens, which formerly required 20 seconds to appear,
would appear in less than 10 seconds using cost based. The customer service representatives
greeted this with a great deal of enthusiasm. However, when the batch cycle ran for payroll the
party ended. Payroll was extremely slow. So, the database was restarted under rules in order to
finish payroll in a reasonable amount of time.
Later Jim, was very surprised to find the users insisting he switch the system back to the way
you had it before payroll. The users perception of online performance under CBO was so much
better that they agreed to limit batch jobs to designated windows of time. The database was
13
manually rebooted at the start and end of each batch window in order to run RULES during batch
jobs and cost for online access.
Of course, that was not an ideal situation. So, significant effort was devoted to figuring out how
to improve batch performance so the system could remain in cost based mode 100% of the time.
Eventually, a solution was found. The key is to use FIRST_ROWS along with carefully tuning
the indexes in the database. The following case study shows how one job was improved by the
use of the CBO.
Rules Based
Cost Based
20 seconds
9 seconds
business expenses
4 seconds
2 seconds
parking expenses
3 seconds
1 second
5 seconds
1 second
benefits
33 seconds
25 seconds
paycheck review
15 seconds
11 seconds
As the data demonstrates, online access is often faster under cost based than under rules. The
difference in times is not always dramatic; however, in terms of user perception, the difference is
significant.
6 Batch Jobs
6.1 General Information
As mentioned previously, the cost based optimizer can have a terrible affect on batch jobs for
Peoplesoft. However, that can be fixed. The key is to use FIRST_ROWS along with carefully
tuning the indexes in the database. The resulting system will produce performance equal or
superior to a rule based system. After tuning, the performance will almost always be better than a
vanilla Peoplesoft installation using rules.
There are a wide variety of jobs which take place during the payroll cycle. Two of the major jobs
will be covered in this section. Those are the payroll jobs: calc and confirm. Calc jobs can be
14
extremely time consuming. To help speed the process, Peoplesoft advises to limit the number of
employees in individual paygroups to a very small number. That solution, while workable, is not
always very useful. In addition, while it does speed up the process overall, the Calc process itself
remains quite inefficient. As it turns out, the SQL used for the Calc jobs is quite similar to the
SQL used for the confirm jobs. So, tuning for one is quite likely to improve the performance of
the other.
A third type of job is actually a general group of jobs. These are custom reports. Jims system
has a large number of reports run via SQR against the database. These must be individually tuned
to ensure proper performance.
So, Jim set out to capture the SQL running against the database for each of these scenarios.
During this effort he used two tools. One was Quest Softwares SQLab Tuner. This allowed you
to create a repository, which collects all of the SQL issued during a batch job. The second tool
was a series of scripts which capture the SQL for processes running against the database. The
scripts also can be used to produce explain plans and tkprof output (see appendix for scripts.)
Although not all of the many enhancements made to the database will be covered by this paper,
the following section provides a case study showing how to improve the performance of the calc
routines dramatically. The results of a properly tuned cost based database are almost always
faster than an RBO database.
15
,PS_PERSONAL_DATAP
WHEREA.COMPANY='046'
ANDA.PAYGROUP='A01'
ANDA.EFFDT<='03DEC1999'
ANDA.EMPL_STATUSIN('A','P','Q','U')
ANDP.EMPLID=A.EMPLID
ANDP.PER_STATUS='E'
ANDNOTEXISTS(SELECT'X'FROMPS_JOBFWHEREF.EMPLID=A.EMPLID
ANDF.EMPL_RCD#=A.EMPL_RCD#
ANDF.EFFDT<='03DEC1999'
ANDF.EFFDT>A.EFFDT
AND(F.EFFDT<='03DEC1999'OR(F.COMPANY='046'
ANDF.PAYGROUP='A01'
ANDF.EMPL_STATUSIN('A','P','Q','U')
ANDF.EFFSEQ=(SELECTMAX(G.EFFSEQ)FROMPS_JOBGWHEREG.EMPLID=F.EMPLID
ANDG.EMPL_RCD#=F.EMPL_RCD#
ANDG.EFFDT=F.EFFDT))))
ANDA.EFFSEQ=(SELECTMAX(H.EFFSEQ)FROMPS_JOBHWHEREH.EMPLID=A.EMPLID
ANDH.EMPL_RCD#=A.EMPL_RCD#
ANDH.EFFDT=A.EFFDT)
ANDNOTEXISTS(SELECT'X'FROMPS_PAY_LINELWHEREL.EMPLID=A.EMPLID
ANDL.EMPL_RCD#=A.EMPL_RCD#
ANDL.COMPANY='046'
ANDL.PAYGROUP='A01'
ANDL.PAY_END_DT='03DEC1999'
ANDL.OFF_CYCLE='N')
ORDERBYA.EMPLIDASC;
16
NUM_ROWS
233417
SQL>selectnum_rowsfromdba_tableswheretable_name='PS_PAY_LINE';
NUM_ROWS
828720
SQL>selectnum_rowsfromdba_tableswheretable_name='PS_PERSONAL_DATA';
NUM_ROWS
32057
SELECTSTATEMENTCost=4404
SORTORDERBY
CONCATENATION
FILTER
NESTEDLOOPS
TABLEACCESSFULLPS_JOB
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
17
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
NESTEDLOOPS
TABLEACCESSFULLPS_JOB
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
NESTEDLOOPS
TABLEACCESSFULLPS_JOB
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
18
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
NESTEDLOOPS
TABLEACCESSFULLPS_JOB
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
59rowsselected.
The query plan indicated a very costly query, which included a full table scan against PS_JOB.
That table scan was obviously a problem, so an index was added to PS_JOB to eliminate the table
scan. Both a normal index and a bitmapped index were compared. This situation was an ideal
candidate for a bitmapped index. Comparing performance between a normal index and the bitmapped index, the bit-mapped index produced marginally better performance.
Figure 9: PS_JOB1_NDX
createbitmapindexps_job1_ndxonps_job(company,paygroup);
analyzeindexps_job1_ndxestimatestatisticssample30percent;
The CALC query performed considerably better with an index. The runtime decreased to 16 to
17 minutes; however, that still was not fast enough.
Figure 10: Bit Map Explain
SQL>@explain
19
QueryPlan
SELECTSTATEMENTCost=68
SORTORDERBY
CONCATENATION
FILTER
NESTEDLOOPS
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPS_JOB1_NDX
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
NESTEDLOOPS
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPS_JOB1_NDX
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
20
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
NESTEDLOOPS
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPS_JOB1_NDX
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_PAY_LINE
INDEXRANGESCANPS#PAY_LINE
SORTAGGREGATE
INDEXRANGESCANPSAJOB
FILTER
TABLEACCESSBYROWIDPS_JOB
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
NESTEDLOOPS
TABLEACCESSBYROWIDPS_JOB
21
INDEXRANGESCANPS_JOB1_NDX
TABLEACCESSBYROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
At this point a comparison to rules mode was made. It turned out that the bit mapped index
brought performance up to par with rules based optimizer. The Calc completed in 15:09.08
minutes under rules.
Since it was going to be necessary to better the performance even further, tkprof was used to get
more detailed information about the query.
Figure 11: TKPROF
TKPROF:Release7.3.4.0.0ProductiononThuDec210:22:231999
Copyright(c)OracleCorporation1979,1996.Allrightsreserved.
Tracefile:ora_26971.trc
Sortoptions:prselaexeelafchela
********************************************************************************
count=numberoftimesOCIprocedurewasexecuted
cpu=cputimeinsecondsexecuting
elapsed=elapsedtimeinsecondsexecuting
disk=numberofphysicalreadsofbuffersfromdisk
query=numberofbuffersgottenforconsistentread
current=numberofbuffersgottenincurrentmode(usuallyforupdate)
rows=numberofrowsprocessedbythefetchorexecutecall
********************************************************************************
SELECTA.EMPLID
,A.EMPL_RCD#
FROMPS_JOBA
,PS_PERSONAL_DATAP
WHEREA.COMPANY='046'
ANDA.PAYGROUP='A01'
ANDA.EFFDT<='03DEC1999'
22
ANDA.EMPL_STATUSIN('A','P','Q','U')
ANDP.EMPLID=A.EMPLID
ANDP.PER_STATUS='E'
ANDNOTEXISTS(SELECT'X'FROMPS_JOBFWHEREF.EMPLID=A.EMPLID
ANDF.EMPL_RCD#=A.EMPL_RCD#
ANDF.EFFDT<='03DEC1999'
ANDF.EFFDT>A.EFFDT
AND(F.EFFDT<='03DEC1999'OR(F.COMPANY='046'
ANDF.PAYGROUP='A01'
ANDF.EMPL_STATUSIN('A','P','Q','U')
ANDF.EFFSEQ=(SELECTMAX(G.EFFSEQ)FROMPS_JOBGWHEREG.EMPLID=F.EMPLID
ANDG.EMPL_RCD#=F.EMPL_RCD#
ANDG.EFFDT=F.EFFDT))))
ANDA.EFFSEQ=(SELECTMAX(H.EFFSEQ)FROMPS_JOBHWHEREH.EMPLID=A.EMPLID
ANDH.EMPL_RCD#=A.EMPL_RCD#
ANDH.EFFDT=A.EFFDT)
ANDNOTEXISTS(SELECT'X'FROMPS_PAY_LINELWHEREL.EMPLID=A.EMPLID
ANDL.EMPL_RCD#=A.EMPL_RCD#
ANDL.COMPANY='046'
ANDL.PAYGROUP='A01'
ANDL.PAY_END_DT='03DEC1999'
ANDL.OFF_CYCLE='N')
ORDERBYA.EMPLIDASC
callcountcpuelapseddiskquerycurrentrows
Parse10.790.8930640
Execute10.000.000000
Fetch11056.251253.051024881661197812
total31057.041253.9410249116611977212
23
Missesinlibrarycacheduringparse:1
Optimizergoal:FIRST_ROWS
Parsinguserid:269(SYSADM)
RowsExecutionPlan
0SELECTSTATEMENTGOAL:FIRST_ROWS
12SORT(ORDERBY)
0CONCATENATION
753FILTER
753NESTEDLOOPS
233376TABLEACCESSGOAL:ANALYZED(FULL)OF'PS_JOB'
753TABLEACCESSGOAL:ANALYZED(BYROWID)OF
'PS_PERSONAL_DATA'
1506INDEXGOAL:ANALYZED(RANGESCAN)OF
'PS_PERSONAL_DATA'(NONUNIQUE)
32361TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_PAY_LINE'
106661796INDEXGOAL:ANALYZED(RANGESCAN)OF'PS#PAY_LINE'
(NONUNIQUE)
22090SORT(AGGREGATE)
38167INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
12632FILTER
12632TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_JOB'
12644INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
0SORT(AGGREGATE)
0INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
0FILTER
24
0NESTEDLOOPS
233376TABLEACCESSGOAL:ANALYZED(FULL)OF'PS_JOB'
0TABLEACCESSGOAL:ANALYZED(BYROWID)OF
'PS_PERSONAL_DATA'
0INDEXGOAL:ANALYZED(RANGESCAN)OF
'PS_PERSONAL_DATA'(NONUNIQUE)
32361TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_PAY_LINE'
106661796INDEXGOAL:ANALYZED(RANGESCAN)OF'PS#PAY_LINE'
(NONUNIQUE)
22090SORT(AGGREGATE)
38167INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
12632FILTER
12632TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_JOB'
12644INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
0SORT(AGGREGATE)
0INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
1422FILTER
1422NESTEDLOOPS
233376TABLEACCESSGOAL:ANALYZED(FULL)OF'PS_JOB'
1422TABLEACCESSGOAL:ANALYZED(BYROWID)OF
'PS_PERSONAL_DATA'
2844INDEXGOAL:ANALYZED(RANGESCAN)OF
'PS_PERSONAL_DATA'(NONUNIQUE)
32361TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_PAY_LINE'
106661796INDEXGOAL:ANALYZED(RANGESCAN)OF'PS#PAY_LINE'
(NONUNIQUE)
22090SORT(AGGREGATE)
38167INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
25
(NONUNIQUE)
12632FILTER
12632TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_JOB'
12644INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
0SORT(AGGREGATE)
0INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
47360FILTER
47360NESTEDLOOPS
233376TABLEACCESSGOAL:ANALYZED(FULL)OF'PS_JOB'
47360TABLEACCESSGOAL:ANALYZED(BYROWID)OF
'PS_PERSONAL_DATA'
94720INDEXGOAL:ANALYZED(RANGESCAN)OF
'PS_PERSONAL_DATA'(NONUNIQUE)
32361TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_PAY_LINE'
106661796INDEXGOAL:ANALYZED(RANGESCAN)OF'PS#PAY_LINE'
(NONUNIQUE)
22090SORT(AGGREGATE)
38167INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
12632FILTER
12632TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_JOB'
12644INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
0SORT(AGGREGATE)
0INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
************************************************************************
26
The Tkprof output made it readily apparent that the index scan of PS#PAY_LINE was
tremendously expensive. The major problem was the number of blocks being accessed to get the
PS_PAY_LINE data.
Given that information, efforts re-focussed on access to PS_PAY_LINE. The CALC query tries
to access the following fields:
emplid, empl_rcd#, company, paygroup, pay_end_dt, and off_cycle.
The PS#PAY_LINE index being used was significantly wider than needed for this query. So an
index targeted specifically for the CALC query was created:
The CALC query was then tested against the system. The results were fabulous. The CALC
query finished in 1:00.51 minutes.
SELECTA.EMPLID
27
,A.EMPL_RCD#
FROMPS_JOBA
,PS_PERSONAL_DATAP
WHEREA.COMPANY='046'
ANDA.PAYGROUP='A01'
ANDA.EFFDT<='03DEC1999'
ANDA.EMPL_STATUSIN('A','P','Q','U')
ANDP.EMPLID=A.EMPLID
ANDP.PER_STATUS='E'
ANDNOTEXISTS(SELECT'X'FROMPS_JOBFWHEREF.EMPLID=A.EMPLID
ANDF.EMPL_RCD#=A.EMPL_RCD#
ANDF.EFFDT<='03DEC1999'
ANDF.EFFDT>A.EFFDT
AND(F.EFFDT<='03DEC1999'OR(F.COMPANY='046'
ANDF.PAYGROUP='A01'
ANDF.EMPL_STATUSIN('A','P','Q','U')
ANDF.EFFSEQ=(SELECTMAX(G.EFFSEQ)FROMPS_JOBGWHEREG.EMPLID=F.EMPLID
ANDG.EMPL_RCD#=F.EMPL_RCD#
ANDG.EFFDT=F.EFFDT))))
ANDA.EFFSEQ=(SELECTMAX(H.EFFSEQ)FROMPS_JOBHWHEREH.EMPLID=A.EMPLID
ANDH.EMPL_RCD#=A.EMPL_RCD#
ANDH.EFFDT=A.EFFDT)
ANDNOTEXISTS(SELECT'X'FROMPS_PAY_LINELWHEREL.EMPLID=A.EMPLID
ANDL.EMPL_RCD#=A.EMPL_RCD#
ANDL.COMPANY='046'
ANDL.PAYGROUP='A01'
ANDL.PAY_END_DT='03DEC1999'
ANDL.OFF_CYCLE='N')
ORDERBYA.EMPLIDASC
callcountcpuelapseddiskquerycurrentrows
28
Parse10.070.0700200
Execute10.000.000000
Fetch156.6987.91106106493984012
total356.7687.981061064939842012
Missesinlibrarycacheduringparse:1
Optimizergoal:FIRST_ROWS
Parsinguserid:269(SYSADM)
RowsExecutionPlan
0SELECTSTATEMENTGOAL:FIRST_ROWS
12SORT(ORDERBY)
49535FILTER
49535NESTEDLOOPS
53695TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_JOB'
53695BITMAPCONVERSION(TOROWIDS)
12BITMAPINDEX(SINGLEVALUE)OF'PS_JOB1_NDX'
49535TABLEACCESSGOAL:ANALYZED(BYROWID)OF
'PS_PERSONAL_DATA'
99070INDEXGOAL:ANALYZED(RANGESCAN)OF
'PS_PERSONAL_DATA'(NONUNIQUE)
47944INDEXGOAL:ANALYZED(RANGESCAN)OF'PS_PAY_LINE1_NDX'
(NONUNIQUE)
21523SORT(AGGREGATE)
37344INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
12632FILTER
12632TABLEACCESSGOAL:ANALYZED(BYROWID)OF'PS_JOB'
29
12644INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
0SORT(AGGREGATE)
0INDEXGOAL:ANALYZED(RANGESCAN)OF'PSAJOB'
(NONUNIQUE)
************************************************************************
The number of blocks processed using the new index were significantly fewer than in the original
query.
30
Initially, Raman examined the top ten processes (CPU and memory) to identify problem queries.
Sometimes an analyst would call the DBA asking for help on a specific query. Addressing the
issue on a case-by-case basis provided little relief. The queries continued to change which
constantly caused new problems. A more general solution was needed.
It was obvious the situation was crying for intelligent optimizer choices. Most analysts do not
want to be bothered with join orders and careful planning of SQL statements. They are concerned
with coding business logic. However, it was impossible to implement the CBO for the system
without going through a significant stage of testing and planning. An interim solution was
required.
31
Time (seconds)
200.00
CBO
100.00
0.00
RBO
CBO
0.06
32
33
ANDA1.OPRID='BATRAR'
ANDE.EMPLID=A1.EMPLID
ANDG.EMPLID=A.EMPLID
ANDG.BALANCE_YEARIN(1998,1999)
ANDG.BALANCE_PERIODIN(1,2,3,8,9,10,11,12)
ANDG.BALANCE_PERIOD=(SELECTMAX(BALANCE_PERIOD)FROMPS_EARNINGS_BALGG
WHEREGG.COMPANY=G.COMPANY
ANDGG.ERNCD=G.ERNCD
ANDGG.EMPLID=G.EMPLID
ANDGG.BALANCE_ID=G.BALANCE_ID
ANDGG.BALANCE_YEAR=G.BALANCE_YEAR)
AND(A.EFFDT=
(SELECTMAX(EFFDT)FROMPS_K_JOB_QUERY_VW
WHEREA.EMPLID=EMPLID
ANDA.EMPL_RCD#=EMPL_RCD#
ANDEFFDT<=SYSDATE)
ANDA.EFFSEQ=
(SELECTMAX(EFFSEQ)FROMPS_K_JOB_QUERY_VW
WHEREA.EMPLID=EMPLID
ANDA.EMPL_RCD#=EMPL_RCD#
ANDA.EFFDT=EFFDT)
ANDB.EFFDT=
(SELECTMAX(EFFDT)FROMPS_COMPANY_TBL
WHEREB.COMPANY=COMPANY
ANDEFFDT<=A.EFFDT)
ANDC.EFFDT=
(SELECTMAX(EFFDT)FROMPS_LOCATION_TBL
WHEREC.LOCATION=LOCATION
ANDEFFDT<=A.EFFDT)
ANDD.EFFDT=
(SELECTMAX(EFFDT)FROMPS_K_CO_WCOMP_TBL
34
WHERED.COMPANY=COMPANY
ANDD.WORKERS_COMP_CD=WORKERS_COMP_CD
ANDEFFDT<=A.EFFDT)
ANDF.EFFDT=
(SELECTMAX(EFFDT)FROMPS_PAYGROUP_TBL
WHEREF.COMPANY=COMPANY
ANDF.PAYGROUP=PAYGROUP
ANDEFFDT<=A.EFFDT)
ANDH.EFFDT=
(SELECTMAX(EFFDT)FROMPS_EARNINGS_TBL
WHEREH.ERNCD=ERNCD
ANDEFFDT<=SYSDATE)
)
ExecutionPlanfortheabovequery:
QueryPlan
SELECTSTATEMENTCost=
CONCATENATION
FILTER
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
35
TABLEACCESSBYINDEXROWID
PS_SCRTY_TBL_SUPRV
INDEXRANGESCAN
PSASCRTY_TBL_SUPRV
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
TABLEACCESSBYINDEXROWID
PS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_PAYGROUP_TBL
INDEXRANGESCANPS#PAYGROUP_TBL
TABLEACCESSBYINDEXROWIDPS_K_CO_WCOMP_TBL
INDEXRANGESCANPS_K_CO_WCOMP_TBL
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_EARNINGS_BAL
INDEXRANGESCANPSBEARNINGS_BAL
TABLEACCESSBYINDEXROWIDPS_EARNINGS_TBL
INDEXRANGESCANPS#EARNINGS_TBL
TABLEACCESSBYINDEXROWIDPS_LOCATION_TBL
INDEXRANGESCANPS#LOCATION_TBL
TABLEACCESSBYINDEXROWIDPS_COMPANY_TBL
INDEXRANGESCANPS#COMPANY_TBL
SORTAGGREGATE
INDEXRANGESCANPS_EARNINGS_BAL
SORTAGGREGATE
INDEXRANGESCANPSDJOB
SORTAGGREGATE
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPSDJOB
SORTAGGREGATE
36
INDEXRANGESCANPS_COMPANY_TBL
SORTAGGREGATE
INDEXRANGESCANPS_LOCATION_TBL
SORTAGGREGATE
INDEXRANGESCANPS_K_CO_WCOMP_TBL
SORTAGGREGATE
INDEXRANGESCANPS_PAYGROUP_TBL
SORTAGGREGATE
INDEXRANGESCANPS_EARNINGS_TBL
SORTAGGREGATE
INDEXRANGESCANPSDJOB
SORTAGGREGATE
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPSDJOB
FILTER
TABLEACCESSBYINDEXROWIDPSTREENODE
INDEXRANGESCANPSCPSTREENODE
INDEXRANGESCANPS#SCRTY_TBL_SUPRV
FILTER
SORTAGGREGATE
INDEXRANGESCANPS_EARNINGS_BAL
SORTAGGREGATE
INDEXRANGESCANPSDJOB
SORTAGGREGATE
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPSDJOB
SORTAGGREGATE
INDEXRANGESCANPS_COMPANY_TBL
SORTAGGREGATE
INDEXRANGESCANPS_LOCATION_TBL
SORTAGGREGATE
37
INDEXRANGESCANPS_K_CO_WCOMP_TBL
SORTAGGREGATE
INDEXRANGESCANPS_PAYGROUP_TBL
SORTAGGREGATE
INDEXRANGESCANPS_EARNINGS_TBL
SORTAGGREGATE
INDEXRANGESCANPSDJOB
SORTAGGREGATE
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPSDJOB
FILTER
TABLEACCESSBYINDEXROWIDPSTREENODE
INDEXRANGESCANPSCPSTREENODE
INDEXRANGESCANPS#SCRTY_TBL_SUPRV
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_COMPANY_TBL
INDEXRANGESCANPS#COMPANY_TBL
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_LOCATION_TBL
INDEXRANGESCANPS#LOCATION_TBL
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_EARNINGS_TBL
INDEXRANGESCANPS#EARNINGS_TBL
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_EARNINGS_BAL
INDEXRANGESCANPSBEARNINGS_BAL
NESTEDLOOPS
INDEXUNIQUESCANPS_PERSONAL_DATA
NESTEDLOOPS
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
38
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
TABLEACCESSBYINDEXROWID
PS_SCRTY_TBL_SUPRV
INDEXRANGESCAN
PSASCRTY_TBL_SUPRV
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPS#JOB
TABLEACCESSBYINDEXROWID
PS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_PAYGROUP_TBL
INDEXRANGESCANPS#PAYGROUP_TBL
TABLEACCESSBYINDEXROWIDPS_K_CO_WCOMP_TBL
INDEXRANGESCANPS_K_CO_WCOMP_TBL
Note: This plan is truncated for printing here since it repeats itself for every employee in the
IN clause. The complete execution plan, if printed goes onto about 5-6 pages. The RULE based
optimizer is not able to handle an IN clause too well.
39
PS_K_CO_WCOMP_TBLD,PS_PERSONAL_DATAE,
PS_PAYGROUP_TBLF,PS_EARNINGS_BALG,PS_EARNINGS_TBLH
WHEREWHEREA.EMPLIDIN
('00156','00871','00959','01203','01706','01749','01915','02316','02475','02628','02967','
03403','03426','03476','03583','04267','05130','05423','06107','06108','06303','06576','06
771','07252','07282','07422','07463','08380','09165','09340','09373','09442','09531','0992
6','10576','11496','11886','12028','12038','12336','12530','13050','14336','14471','14972'
,'16956','18069','18070','18362','18442','18816','19243','19762','19857','19858','20560','
21517','21687','21791','22589','22718','22910','23097','23936','23960','24033','24046','24
108','24115','24168','24308','24404','24444','24768','24921','25028','25137','25171','2546
9','25480','26239','26980','27160','27217','27218','27410','27569','27729','28065','29750'
,'30950','31508','31960','32249','32470','32825','32952','33803','33835','37430','37865','
38266','38543','45433','49184','54100','54840','63550','68060','68690','70137','71818','75
420','76390','78090','80500','81220','83696','83985','89930','93892','97288')
ANDB.COMPANY=A.COMPANY
ANDC.LOCATION=A.LOCATION
ANDD.WORKERS_COMP_CD=A.WORKERS_COMP_CD
ANDD.COMPANY=A.COMPANY
ANDE.EMPLID=A.EMPLID
ANDF.PAYGROUP=A.PAYGROUP
ANDF.COMPANY=A.COMPANY
ANDH.ERNCD=G.ERNCD
ANDA.EMPLID=A1.EMPLID
ANDA.EMPL_RCD#=A1.EMPL_RCD#
ANDA1.OPRID='BATRAR'
ANDE.EMPLID=A1.EMPLID
ANDG.EMPLID=A.EMPLID
ANDG.BALANCE_YEARIN(1998,1999)
ANDG.BALANCE_PERIODIN(1,2,3,8,9,10,11,12)
ANDG.BALANCE_PERIOD=(SELECTMAX(BALANCE_PERIOD)FROMPS_EARNINGS_BALGG
WHEREGG.COMPANY=G.COMPANY
ANDGG.ERNCD=G.ERNCD
ANDGG.EMPLID=G.EMPLID
ANDGG.BALANCE_ID=G.BALANCE_ID
40
ANDGG.BALANCE_YEAR=G.BALANCE_YEAR)
AND(A.EFFDT=
(SELECTMAX(EFFDT)FROMPS_K_JOB_QUERY_VW
WHEREA.EMPLID=EMPLID
ANDA.EMPL_RCD#=EMPL_RCD#
ANDEFFDT<=SYSDATE)
ANDA.EFFSEQ=
(SELECTMAX(EFFSEQ)FROMPS_K_JOB_QUERY_VW
WHEREA.EMPLID=EMPLID
ANDA.EMPL_RCD#=EMPL_RCD#
ANDA.EFFDT=EFFDT)
ANDB.EFFDT=
(SELECTMAX(EFFDT)FROMPS_COMPANY_TBL
WHEREB.COMPANY=COMPANY
ANDEFFDT<=A.EFFDT)
ANDC.EFFDT=
(SELECTMAX(EFFDT)FROMPS_LOCATION_TBL
WHEREC.LOCATION=LOCATION
ANDEFFDT<=A.EFFDT)
ANDD.EFFDT=
(SELECTMAX(EFFDT)FROMPS_K_CO_WCOMP_TBL
WHERED.COMPANY=COMPANY
ANDD.WORKERS_COMP_CD=WORKERS_COMP_CD
ANDEFFDT<=A.EFFDT)
ANDF.EFFDT=
(SELECTMAX(EFFDT)FROMPS_PAYGROUP_TBL
WHEREF.COMPANY=COMPANY
ANDF.PAYGROUP=PAYGROUP
ANDEFFDT<=A.EFFDT)
ANDH.EFFDT=
(SELECTMAX(EFFDT)FROMPS_EARNINGS_TBL
41
WHEREH.ERNCD=ERNCD
ANDEFFDT<=SYSDATE)
)
ExplainPlanfortheaboveSQL:
QueryPlan
SELECTSTATEMENTCost=35
FILTER
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
NESTEDLOOPS
INLISTITERATORCONCATENATED
TABLEACCESSBYINDEXROWIDPS_JOB
INDEXRANGESCANPSDJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
TABLEACCESSBYINDEXROWIDPS_COMPANY_TBL
INDEXRANGESCANPS_COMPANY_TBL
SORTAGGREGATE
INDEXRANGESCAN
PS_COMPANY_TBL
TABLEACCESSBYINDEXROWIDPS_JOB
42
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
TABLEACCESSBYINDEXROWIDPS_K_CO_WCOMP_TBL
INDEXRANGESCANPS#K_CO_WCOMP_TBL
TABLEACCESSBYINDEXROWIDPS_PAYGROUP_TBL
INDEXRANGESCANPS#PAYGROUP_TBL
TABLEACCESSBYINDEXROWIDPS_LOCATION_TBL
INDEXRANGESCANPS_LOCATION_TBL
SORTAGGREGATE
INDEXRANGESCANPS_LOCATION_TBL
TABLEACCESSBYINDEXROWIDPS_EARNINGS_BAL
INDEXRANGESCANPS_EARNINGS_BAL
SORTAGGREGATE
INDEXRANGESCANPS_EARNINGS_BAL
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_PERSONAL_DATA
INDEXUNIQUESCANPS_PERSONAL_DATA
TABLEACCESSBYINDEXROWIDPS_EARNINGS_TBL
INDEXRANGESCANPS_EARNINGS_TBL
SORTAGGREGATE
INDEXRANGESCANPS_EARNINGS_TBL
TABLEACCESSBYINDEXROWIDPS_SCRTY_TBL_SUPRV
INDEXRANGESCANPSASCRTY_TBL_SUPRV
FILTER
TABLEACCESSBYINDEXROWIDPSTREENODE
INDEXRANGESCANPSCPSTREENODE
INDEXRANGESCANPS#SCRTY_TBL_SUPRV
SORTAGGREGATE
INDEXRANGESCANPS_PAYGROUP_TBL
SORTAGGREGATE
43
TABLEACCESSFULLPS_K_CO_WCOMP_TBL
SORTAGGREGATE
INDEXRANGESCANPSAJOB
SORTAGGREGATE
INDEXRANGESCANPSAJOB
Note: The IN statement is handled very well by the Cost-Based Optimizer and the INLIST
Iteration works wonders .
44
9 Appendix A: Scripts
allActive.sql
Thisroutinewillproducealist
ofallactiveuserscurrentlyconnectedtothe
system.Thelistwillindicatevarious
thingsincludingthestatusoftheconnection,
thetypeofcommandcurrentlybeingexecuted,
andwhetherthesessionisblockedbyanother
user.
authorJamesE.Strange
settimingoff
setpauseoff
setpagesize9000
setlinesize100
columnsidheadingSIDformat999
columnspidheadingOSPIDformat999999
columnusernameheadingUSERformatA10
columnosuserheadingOSUSERformatA10
columnmachineheadingMACHINEformatA22
columnstatusheadingSTATUSformatA8
columnnameheadingCOMMANDformatA15
columnlockwaitformatA8
selects.sid,proc.spid,s.username,s.osuser,
s.machine,s.status,a.name,nvl(s.lockwait,'NO')BLOCKED
fromv$sessions,audit_actionsa,
v$processproc
wherea.action=s.command
45
andproc.addr=s.paddr
ands.usernameisnotnull
ands.status='ACTIVE'
orderbys.status,s.sid
/
sql.sql
Thisroutineliststhesqlforaselected
sid.Thesecondsecondquerywillindicate
theoptimizermodeandthenumberofrows
processedbythequery.
authorJamesE.Strange
selecttext.sql_text
from
v$sqltext_with_newlinestext,v$sessionsess
where
text.address=sess.sql_addressand
text.hash_value=sess.sql_hash_valueand
sess.sid=&sid
orderbypiece
/
checkLatches.sql
Author:JamesE.Strange
Thisscriptdisplaysthestatusoflatches.Itlooksatthemfrom3differentways.
Thefirstsectionsimplyliststhelatchstatistics.
Thesecondsectionlooksatthewillingtowaitstats.
Thelastsectionlooksatthenotwillingtowaitpointofview.
46
setpagesize900
setlinesize120
columnnameformatA40
selectl.latch#latch#,l.missesmisses,l.getsgets,n.namenamefromv$latchl,
v$latchnamenwheren.latch#=l.latch#
orderbyname
/
selectnamelatch_name,gets,misses,
round((getsmisses)/decode(gets,0,1,gets),3)hit_ratio,
sleeps,round(sleeps/decode(misses,0,1,misses),3)
"SLEEPS/MISS"
fromv$latch
wheregets!=0
orderbyname
/
selectnamelatch_name,immediate_getsnowait_gets,
immediate_missesnowait_miss,
round((immediate_gets/(immediate_gets+immediate_misses)),3)nowait_hit_ratio
fromv$latch
whereimmediate_gets+immediate_misses!=0
orderbyname
/
makeExplain.sql
Thisroutineliststhesqlforaselected
sidintoafile.Theoutputisformattedto
makeitrelativelysimpletocreateafileto
useforgettinganexplainplan.Thisscript
47
assumesthefilenameshouldbeoftheform'test#'
wherethe#isanumber.Thescriptwillprompt
foranumbertosubstituteforthe#.
authorJamesE.Strange
setechooff
setheadingoff
setlinesize64
spooltest.sql
select'explainplansetstatement_id=''test&1''for'fromdual;
select
rtrim(text.sql_text)
from
v$sqltext_with_newlinestext,v$sessionsess
where
text.address=sess.sql_addressand
text.hash_value=sess.sql_hash_valueand
sess.sid=&sid
orderbypiece
;
select';'fromdual;
spooloff
48
TABLE_NAME
INDEX_NAME
COLUMN_NAME
PS_EMPLOYEES
PS_EMPLOYEES1_NDX
GL_PAY_TYPE
PS_EMPLOYEES
EMPL_STATUS
PS_EMPLOYEES
EMPLID
PS_EMPLOYEES
EMPL_RCD#
PS_EMPLOYEES
EFFDT
PS_EMPLOYEES
EFFSEQ
PS_JOB
COMPANY
PS_JOB1_NDX
PS_JOB
PAYGROUP
PS_JOB
GL_PAY_TYPE
PS_JOB2_NDX
PS_JOB
EMPLID
PS_JOB
GRADE
PS_JOB
SAL_ADMIN_PLAN
PS_JOB
POSITION_NBR
PS_JOB
EMPL_RCD#
PS_JOB
EFFDT
PS_PAY_DEDUCTION
PS_PAY_DEDUCTION1_NDX
DEDCD
PS_PAY_LINE
PS_PAY_LINE1_NDXEMPLID
PS_PAY_LINE
EMPL_RCD#
PS_PAY_LINE
COMPANY
PS_PAY_LINE
PAYGROUP
PS_PAY_LINE
PAY_END_DT
PS_PAY_LINE
OFF_CYCLE
49
PS_PAY_LINE
PS_PAY_LINE2_NDXEMPL_RCD#
PS_PAY_LINE
EMPLID
PS_PAY_LINE
COMPANY
PS_PERSONAL_DATA
PER_STATUS
PS_PERSONAL_DATA1_NDX
PS_PERSONAL_DATA
PER_TYPE
PS_PERSONAL_DATA
EMPLID
PS_W2_EE
EMPLID
PS_W2_EE1_NDX
PS_W2_EE
PROCESS_FLAG
HPUX10.20
T600system
6CPUs
3.5GigabytesofRAM
Oracle7.3.4.2
SGA=500MB
OptimizerMode
First_Rows
ClientMachine
CompaqArmada
333MZCPU
96MBRAM
ApplicationServer
Coresidentondatabaseserver
DatabaseSize
30Gig17000employees
PSApplications
PSVersion
HR,Payroll,Benefits,TimeandLabor,SelfService
7.02
SunSolaris2.5.1
E5000
4CPUs
3.0GigabytesofRAM
50
Oracle8.0.5
SGA=680MB
OptimizerMode
Rule
ClientMachine
DellLaptop
300IIMZCPU
128MBRAM
ApplicationServer
Tuxedo,Logicalthreetier,Coresidentondatabaseserver
DatabaseSize
26Gigapprox.13000employees
PSApplications
HR,Payroll,Benefits
PSVersion
7.03
51