Introduction of Hardware and Environment

1,444 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,444
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
35
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Introduction of Hardware and Environment

  1. 1. G22.2434.01 Fall 2005 Advanced Database Systems Report of Tuning Project By: Yuhong Chen Student ID: N16413151 [See my comments below beginning with “Dennis:” In general a very nice job though I would have like to hear what happened in your data warehouse experiment] Index Introduction of Hardware and Environment ................................................................................................... 2 Case 1: Reduce the size of large update transactions (Ref. Chapter 2.3.2) .................................................. 4 Case 2: Minimizing DISTINCTs (Ref. Chapter 4.6.1) ...................................................................................... 12 Case 3: Query Tuning (Ref. Chapter 4.6) .......................................................................................................... 20 Case 4: Understanding Access Plan (Ref. Appendix D) ................................................................................. 29 Case 5: Troubleshooting (Ref. Chapter 7) ......................................................................................................... 37 Other Tuning Experiences ................................................................................................................................... 40 Appendix: DDL statement of tables and views in case study. 1
  2. 2. 2
  3. 3. Introduction of Hardware and Environment: Our Production Database System: Database system: Oracle 9i – 9.2.0.7 Operation System: IBM AIX 5L – 5.1 AIX Server 1: IBM RS6000 – 6H1 Processor: 4 - way CPUs 750 MHz each Memory: 8 G Disks: two 18G disks Raid 1 for applications Twenty-four (24) disks (total size 225 G) RAID 1 for data AIX Server 2: IBM RS6000 – 6F1 Processor: 4 – way CPUs 600 MHz each Memory: 8 G Disks: two 36G disks Raid 1 for applications Ten (10) 72G disks total size 350G RAID 10 for data Comparing Database System: Database system: Microsoft SQL Server 2000 with SP 3 Operation System: Dell OPTIPLEX GX-150 Microsoft Windows XP Professional Workstation Processor: Pentium III 996 MHz Memory: 512 M Disk: One internal IDE disk size 37.2 G About the system of this tuning project: The databases I use for this tuning project is PeopleSoft ERP application for Finance and Human Resource Management. Oracle database engine is used as backend database server. On the above Server list, AIX Server 1 is our production server. AIX Server 2 is Disaster Recovery Server. Because PeopleSoft ERP system is a mature application, we just need a few coding for customize the modules. Almost all problem queries are generated by “Query Builder” for Ad Hoc reports. Our users do not know how to coding SQL. PeopleSoft Application supports multi-database servers: Oracle, IBM DB2, SQL Server, Informix…… PeoperSoft builds the database structure as portable as he can! There are not 3
  4. 4. primary key and foreign key for data integration, PeopleSoft use its application to control the data integration. There more than 7,000 tables, 3,000 indexes and 2,000 views in Finance database. There are more than 5,000 tables, 3,000 indexes and 2,000 indexes in HRMS database. For security reason, views are used for different user groups. Most of those views are built on views too (depth to several levels). If we just simply re-write the problem queries using the base tables of views, user cannot submit it through their GUI application interface. Anyway I still have to do what I can do under those restrictions. 4
  5. 5. Case 1: Reduce the size of large update transactions (Ref. Chapter 2.3.2) Scenario: We have a table named PS_HR_ACCTG_LINE which storages the data of payroll. There are 200,000 to 300,000 rows added each month after payroll run. We need purge those data once a while. Problem: When our HRMS manager tried to purge data, he used query builder GUI to generate the DDL Statement: DELETE FROM PS_HR_ACCTG_LINE A WHERE A.JOURNAL_DATA < TO_DATE(‘2005-07-01’,’YYYY-MM-DD’); He hits the error “rollback tablespace runs out of space” all the time. Description of Table PS_HR_ACCTG_LINE: SQL> desc ps_hr_acctg_line Name Null? Type ----------------------------------------- -------- ------------------- RUN_DT DATE SEQNUM NOT NULL NUMBER(38) LINE_NBR NOT NULL NUMBER(38) KK_AMOUNT_TYPE NOT NULL VARCHAR2(1) AUDIT_ACTN NOT NULL VARCHAR2(1) IN_PROCESS_FLG NOT NULL VARCHAR2(1) BUDGET_LINE_STATUS NOT NULL VARCHAR2(1) BUDGET_DT DATE BUSINESS_UNIT_GL NOT NULL VARCHAR2(5) JOURNAL_ID NOT NULL VARCHAR2(10) JOURNAL_DATE DATE JOURNAL_LINE NOT NULL NUMBER(38) ACCOUNT NOT NULL VARCHAR2(10) DEPTID NOT NULL VARCHAR2(10) PROJECT_ID NOT NULL VARCHAR2(15) PRODUCT NOT NULL VARCHAR2(6) FUND_CODE NOT NULL VARCHAR2(5) PROGRAM_CODE NOT NULL VARCHAR2(5) CLASS_FLD NOT NULL VARCHAR2(5) AFFILIATE NOT NULL VARCHAR2(5) OPERATING_UNIT NOT NULL VARCHAR2(8) ALTACCT NOT NULL VARCHAR2(10) STATISTICS_CODE NOT NULL VARCHAR2(3) MONETARY_AMOUNT NOT NULL NUMBER(15,2) FOREIGN_AMOUNT NOT NULL NUMBER(15,2) FOREIGN_CURRENCY NOT NULL VARCHAR2(3) RT_TYPE NOT NULL VARCHAR2(5) RATE_MULT NOT NULL NUMBER(15,8) RATE_DIV NOT NULL NUMBER(15,8) STATISTIC_AMOUNT NOT NULL NUMBER(15,2) JRNL_LN_REF NOT NULL VARCHAR2(10) OPEN_ITEM_STATUS NOT NULL VARCHAR2(1) LINE_DESCR NOT NULL VARCHAR2(30) JRNL_LINE_STATUS NOT NULL VARCHAR2(1) JOURNAL_LINE_DATE DATE BUSINESS_UNIT NOT NULL VARCHAR2(5) APPL_JRNL_ID NOT NULL VARCHAR2(10) ACCOUNTING_DT DATE GL_DISTRIB_STATUS NOT NULL VARCHAR2(1) PROCESS_INSTANCE NOT NULL NUMBER(10) CURRENCY_CD NOT NULL VARCHAR2(3) ACCOUNTING_PERIOD NOT NULL NUMBER(38) FISCAL_YEAR NOT NULL NUMBER(38) LEDGER NOT NULL VARCHAR2(10) LEDGER_GROUP NOT NULL VARCHAR2(10) USE_DISTRIBUTION NOT NULL VARCHAR2(1) BUDGET_REF NOT NULL VARCHAR2(8) CHARTFIELD1 NOT NULL VARCHAR2(10) CHARTFIELD2 NOT NULL VARCHAR2(10) CHARTFIELD3 NOT NULL VARCHAR2(10) 5
  6. 6. Indexes on the Table: There are two indexes have been built on this table: 1. Unique index PS_HR_ACCTG_LINE on columns RUN_DT, SEQNUM and LINE_NBR; 2. Unique index PSAHR_ACCTG_LINE on columns ACCTOUNT, PROGRAM_CODE, DEPTID AND PROJECT_ID Analysis: Since I know that the size of our rollback tablespace is 3 times of the size of table PS_HR_ACCTG_LINE, we cannot just enlarge rollback tablespace for this issue. Accord to professor’s book, I decide to try two methods: 1. Reduce the size of this transaction: the data type of column JOURNAL_DATE is date. We can reduce the range of date and cut the big batch to several same batch transactions. 2. There is no index on column JOURNAL_DATE. This update process leaded a full table access on table PS_HR_ACCTG_LINE. I tried to create an index on column JOURNAL_DATE, and compare the response time. (index vs. update) Result: Method 1: When I delete the data from PS_HR_ACCTG_LINE based on every two months, the response time was 35min58sec. 497,282 rows deleted. This is not an acceptable response time. Then I reduce the update on one month each time. The response time was 3min9sec and 217,814 rows deleted. This is an acceptable response time. Parameter (Where clause) Number of deleted rows Response time < ’01-OCT-2004’ 497,282 34 min 58 sec < ’01-SEP-2004’ 217,814 3 min 9 sec < ’01-OCT-2004’ 279,468 4 min 6 sec < ’01-NOV-2004’ 289,912 4 min 52 sec < ’01-DEC-2004’ 286,624 4 min 41 sec < ’01-JAN-2005’ 289,188 4 min 29 sec < ’01-FEB-2005’ 286,350 4 min 8 sec < ’01-MAR-2005’ 291,474 / < ’01-APR-2005’ 291,097 5 min 17 sec < ’01-MAY-2005’ 291,667 4 min 23 sec < ’01-JUN-2005’ 255,387 3 min 51 sec < ’01-JUL-2005’ 222,960 3 min 28 sec 6
  7. 7. 1200 1000 throughput(rows/sec) 800 throughput(rows/se 600 c) 400 200 0 batch size batch size 497282 rows 271047 rows (avarage) Figure case 1.1 Reduce the size of large update transactions. Compare the batch size of 497282 rows and 271047 rows (which is an average of 10 small batch processes), we can see that throughput got extremely improved (5 times). Method 2: The original execute plan of this delete statement is: SQL> delete from ps_hr_acctg_line where journal_date < '01-OCT-05'; 393426 rows deleted. Elapsed: 00:05:16.56 Execution Plan ---------------------------------------------------------- 0 DELETE STATEMENT Optimizer=CHOOSE (Cost=1961 Card=365703 Byt es=12068199) 1 0 DELETE OF 'PS_HR_ACCTG_LINE' 2 1 TABLE ACCESS (FULL) OF 'PS_HR_ACCTG_LINE' (Cost=1961 Car d=365703 Bytes=12068199) Statistics ---------------------------------------------------------- 640 recursive calls 2833791 db block gets 20728 consistent gets 15772 physical reads 403468520 redo size 800 bytes sent via SQL*Net to client 713 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 393426 rows processed We can see there is a full table access on the table PS_HR_ACCTG_LINE. Our update statement bases on a column with type date. I created an index on this column to see if it can improve the response time. After I created the index, the SQL explain plan was as the following: 7
  8. 8. SQL> create index temp_journal_date on ps_hr_acctg_line(journal_date); Index created. Elapsed: 00:00:13.92 SQL> analyze table ps_hr_acctg_line compute statistics; Table analyzed. Elapsed: 00:02:56.93 SQL> delete from ps_hr_acctg_line where journal_date < '01-OCT-05'; 393426 rows deleted. Elapsed: 00:05:12.33 Execution Plan ---------------------------------------------------------- 0 DELETE STATEMENT Optimizer=CHOOSE (Cost=1961 Card=365703 Byt es=12068199) 1 0 DELETE OF 'PS_HR_ACCTG_LINE' 2 1 TABLE ACCESS (FULL) OF 'PS_HR_ACCTG_LINE' (Cost=1961 Car d=365703 Bytes=12068199) Statistics ---------------------------------------------------------- 736 recursive calls 4166821 db block gets 20772 consistent gets 16714 physical reads 482732932 redo size 801 bytes sent via SQL*Net to client 713 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 393426 rows processed Our database’s optimizer mode is CHOOSE, which means Oracle will calculate the cost of processing. Even we created an index on column JOURNAL_DATE, it looks like that Oracle did not use the index. But statistics are little different. We can see that there is 4.23 seconds’ improvement between two elapsed times before/after index created. Compares the statistics, we also can see that “recursive calls, db block gets, redo size etc.” are increased a lot. It is not worth to use those system resources to trade 4.23 seconds response time. [Dennis: Also the delete would update the index all the time.] Testing run on Microsoft SQL Server: About the SQL Server environment Since the hardware of my Dell workstation is not very good, I did not convert my whole ERP database to SQL Server from Oracle database Server. I just copied all tables for all queries which each case needs here from Oracle to SQL server. I also created same indexes, views as we have in Oracle Database. Even though, size of SQL testing database is over 4 G. I could not convert data type BLOB column from Oracle to SQL Server. I removed those columns from those tables with data type “LONG” before I copied them to SQL Server. Anyway, my case study doesn’t need those columns. 8
  9. 9. The queries I ran on two database are little different too. Some single row functions which Oracle SQLPLUS supports are not supported by SQL Server Transact-SQL. I modified those codes of views, queries to make them executable on SQL Server. That means, the result my testing got from Oracle and SQL Server, could not be compare between database levels. It only can be use to compare before or after tuning in same database engine. Result: Number of deleted rows Response time 393,426 47 sec 609,212 33 sec I was very surprised when I got the result. First of all, I found that the batch size has no affect to the response time. Actually, the larger batch update transaction has bigger throughput than the small one. Second, for a single DDL event, the response time of SQL Server is excellent: [Dennis: Interesting.] Throughput between Oracle and SQL Server Throughput (rows/sec) 10000 8000 6000 4000 2000 0 Oracle SQL Server an update transaction with 393426 rows deleted Figure case 1.2 Througput (rows/sec) of same update transactions between Oracle and SQL Server. Compare the batch size of 393426 rows on Oracle Database Engine and MS SQL Server engine, we can see that throughput of SQL Server is almost 7 time more than Oracle. 9
  10. 10. 90000 80000 throughput (rows/sec) 70000 60000 50000 40000 30000 20000 10000 0 393426 rows deleted 609212 rows deleted Figure case 1.3 Througput (rows/sec) of a small update transaction and a big update transaction on SQL Server. Compare the batch size of 393426 rows and 609212 rows on MS SQL Server. We can see that throughput of large update transaction is also bigger. If I have more time for study, I may study what the main factors are which affect the response time between the batch size on different database engines. Log of Test 1: A small batch transaction delete from ps_hr_acctg_line where journal_date < '2005-10-01 00:00:00.000' (393426 row(s) affected) Execution time: 47 seconds Statistics: Counter: Value Average Application Profile Statistics Timer resolution (milliseconds) 0 0 Number of INSERT, UPDATE, DELETE statements 1 0.142857 Rows effected by INSERT, UPDATE, DELETE statements 393426 56203.7 Number of SELECT statements 1 0.714286 Rows effected by SELECT statements 4 3.14286 Number of user transactions 5 4 Average fetch time 0 0 Cumulative fetch time 0 0 Number of fetches 0 0 Number of open statement handles 0 0 Max number of opened statement handles 0 0 Cumulative number of statement handles 0 0 Test 2: A large batch transaction delete from ps_hr_acctg_line where journal_date < '2005-11-01 00:00:00.000' (609212 row(s) affected) Execution time: 33 seconds Statistics: Counter: Value Average Application Profile Statistics Timer resolution (milliseconds) 0 0 Number of INSERT, UPDATE, DELETE statements 1 0.166667 Rows effected by INSERT, UPDATE, DELETE statements 609212 83553.2 Number of SELECT statements 1 0.666667 Rows effected by SELECT statements 4 2.58333 Number of user transactions 5 3.91667 Average fetch time 0 0 10
  11. 11. Cumulative fetch time 0 0 Number of fetches 0 0 Number of open statement handles 0 0 Max number of opened statement handles 0 0 Cumulative number of statement handles 0 0 Why SQL Server runs DELETE statement is more effectible than Oracle? I found that I cannot rollback the deleted rows on SQL Server. On the SQL Server on-line book, under the topic “You are about to delete a row or rows” it says: “Choosing yes will delete the selected row from the table. If you say Yes, the deletion will be immediatedly transmitted to the database. You will not be able to undo this change.” I realized that SQL Server only writes redo logs. Oracle writes redo logs and undo(rollback segements). [Dennis: Does this version of sql server have multiversion read consistency?] Then I did a test of SELECT statement: On Oracle: select * from PS_HR_ACCTG_LINE where JOURNAL_DATE < ’01-OCT-05’; 393426 rows selected. Elapsed: 00:11:32.58 On SQL SERVER: select * from PS_HR_ACCTG_LINE where JOURNAL_DATE < ’2005-10-01 00:00:00.000’; Process dead after 34 min running due to memory leak. I also check the update/insert statement. SQL Server cannot rollback the action of executing an UPDATE/INSERT too. SQL Server is an auto-commit database system. [Dennis: Perhaps you need to begin and end transaction] Summery: On Oracle database: 1. Reduce the size of large update transactions can extremely reduce response time and improve the throughput. 2. When we run update statement, it need bigger redo size. The redo size is not calculated by the size of affected data. On MS SQL Server database: 3. The size of batch update transactions does not affect the response time and throughput. It because that SQL Server is an auto commit database system, it executes DDL statements (insert/update/delete) without undo information. All executed DDL action cannot be undo. Conclusion: Reduce the size of large update transactions will help response time and throughput a lot on non-auto-commit database system (such as Oracle – write undo and redo), but not on auto- commit database system (such as SQL Server - write redo only; IBM DB2 – write redo only; Sybase, Informix and MySQL). 11
  12. 12. *************************** An Extra Test on SQL Server: I discussed with some DBA friends about auto-commit database system and response time of update transactions. They told me that I can turn off auto-commit on one particle transaction on those database systems. Such as on DB2, add the option parameter “+c” before update transaction command to turn off auto-commit; and on SQL Server, auto commit also can be turned off. I tested the response time after I turned off auto commit of SQL Server. I found that auto- commit on/off doesn’t affect the response time – SQL Server still writes redo log only. Set implicit_transaction on Begin tran delete from ps_hr_acctg_line where journal_date < '2005-09-01 00:00:00.000' (83120 row(s) affected) Execution time: 28 seconds Rollback time: 16 seconds delete from ps_hr_acctg_line where journal_date < '2005-10-01 00:00:00.000' (393426 row(s) affected) Execution time: 23 seconds Rollback time: 1 min 33 seconds 20000 throughput (rows/sec) 15000 83120 rows 10000 393426 rows 5000 0 delete rollback Figure case 1.3 Througput (rows/sec) of a small update transaction and a big update transaction on SQL Server after auto-commit turned off. Compare the batch size of 83120 rows and 393426 rows. After auto commit was turned off, the throughput of DETELE doesn’t affect (33 sec. on 393426 rows with auto-commit on, yesterday). The throughput of rollback process of big batch transaction and small batch transaction are similar. We know that the SQL Server is a database only write redo. I think that relation between execution time and batch size depends on database structure which means the database engine is writing undo only or writing undo AND redo. 12
  13. 13. Case 2: Minimizing DISTINCTs (Ref. Chapter 4.6.1) Scenario: Our users use query builder to generate SQL code for their report. They really don’t know how database engine runs SQL. Sometime their queries do not return any result after a few hours running. I helped them to tuning a lot of those problem queries. I found the users add “DISTINCT” to guarantee their queries return unique records all the time, but most of time “DISTINCT” caused the performance problems and those “DISTINCTs” do not needed on the query at all. Problem: I received this problem query on October 3 right after I read section 4.6.1 of professor’s tuning book. I cannot to wait to use the skill I learned from book to tuning the following query: SELECT DISTINCT B.NAME, A.EMPLID, A.EMPL_RCD, TO_CHAR(A.EFFDT,'YYYY-MM-DD'), A.EMPL_STATUS FROM PS_JOB A, PS_B_FAST_EMP_QRY A1, PS_PERSONAL_DTA_VW B, PS_B_FAST_PERS_QRY B1 WHERE A.EMPLID = A1.EMPLID AND A.EMPL_RCD = A1.EMPL_RCD AND A1.ROWSECCLASS = 'CPHR7030' AND B.EMPLID = B1.EMPLID AND B1.ROWSECCLASS = 'CPHR7030' AND ( A.EFFDT = (SELECT MAX(A_ED.EFFDT) FROM PS_JOB A_ED WHERE A.EMPLID = A_ED.EMPLID AND A.EMPL_RCD = A_ED.EMPL_RCD AND A_ED.EFFDT <= SYSDATE) AND A.EFFSEQ = (SELECT MAX(A_ES.EFFSEQ) FROM PS_JOB A_ES WHERE A.EMPLID = A_ES.EMPLID AND A.EMPL_RCD = A_ES.EMPL_RCD AND A.EFFDT = A_ES.EFFDT) AND A.EMPLID = B.EMPLID ); He had been waiting more than 5 hours and got no any date returned! He asked me to kill his session which was processing the query and help tuning it. Description of the involved tables and views in this query: There are 5 tables and 5 views involved in this query. Tables: Like I mentioned above, PS doesn’t use primary key. Here I consider NO NULL with Unique index columns as Key. ***********on FROM clause • PS_JOB, a big table with 217 columns and 87,857 rows Key: emplid, emp_rcd, effdt and effseq. ***********not on FROM clause • PS_PERSON, 10 columns and 13,268 rows Key: emplid • PS_FAST_SCRTY_2, 4 columns and 14,970 rows Key: setid, deptid and rowsecclass • PS_NAMES, 23 columns and 15,179 rows Key: emplid, name_type and effdt 13
  14. 14. • PS_PERS_DATA_EFFDIT, 75 columns and 13,441 rows Key: emplid, effdt Views: ***********on FROM clause • PS_B_FAST_EMP_QRY is a view, built on 3 base tables and 1 view Tables: PS_JOB, PS_PERSON AND PS_FAST_SCRTY_2 View: PS_PERSON_NAME • PS_PERSONAL_DTA_VW, built on 1 view View: PS_PERSONAL_NAME • PS_B_FAST_PERS_QRY, built on 2 base tables and 1 view Tables: PS_JOB and PS_FAST_SCRTY_2 view: PS_PERSONAL_DT_FST ***********not on FROM clause • PS_PERSONAL_NAME Table: PS_NAME • PS_PERSONAL_DT_FST Table: PS_NAME Analysis: On the Section 4.6.1 of Professor’s tuning book, Professor says: Generalizing from this example, we conclude that if the fields returned constitute a key of one table T and all other tables perform an equijoin with T by their keys, then the values returned will contain no duplicates, so DISTINCT will be unnecessary. I will say this skill is the most helpful skill for my environment. I have known that 80% of our problem queries caused by “SELECT DISTINCT”, but I don’t know how to get rid of it. I always joke with my co-workers that “select distinct “ is my nightmare! This tuning skill really helps me get rid of 50% of our problem queries. I used to re-rewrite those problems queries before. Let’s go back to check the example problem query. There are 4 objects on FROM CLAUSE. PS_JOB is a table with key. The other 3 objects are views. We have to find out the columns work as key for the result of those views first. PS_B_FAST_EMP-QRY: base on 3 tables and 1 view, PS_PERSON_NAME PS_PERSONAL_DTA-VW: base on view PS_PERSON_NAME PS_B_FAST_QRY: base on two tables and 1 view: PS_PERSONAL_DT_FST 14
  15. 15. PS_JOB EMPLID: VARCHAR2(11) EMPL_RCD: NUMBER EFFDT: DATE EFFSEQ: NUMBER DEPTID: VARCHAR2(10) JOBCODE: VARCHAR2(6) POSITION_NBR: VARCHAR2(8) GVT_EFFDT: DATE GVT_EFFDT_PROPOSED: DATE GVT_TRANS_NBR: NUMBER GVT_TRANS_NBR_SEQ: NUMBER GVT_WIP_STATUS: VARCHAR2(3) GVT_STATUS_TYPE: VARCHAR2(3) GVT_NOA_CODE: VARCHAR2(3) GVT_LEG_AUTH_1: VARCHAR2(3) GVT_PAR_AUTH_D1: VARCHAR2(25) PS_B_FAST_PERS_QRY GVT_PAR_AUTH_D1_2: VARCHAR2(25) GVT_LEG_AUTH_2: VARCHAR2(3) EMPLID: A.EMPLID GVT_PAR_AUTH_D2: VARCHAR2(25) ROWSECCLASS: SEC.ROWSECCLASS GVT_PAR_AUTH_D2_2: VARCHAR2(25) ACCESS_CD: SEC.ACCESS_CD GVT_PAR_NTE_DATE: DATE GVT_WORK_SCHED: VARCHAR2(1) GVT_ELIG_FEHB: VARCHAR2(3) GVT_FEHB_DT: DATE GVT_PAY_RATE_DETER: VARCHAR2(1) PS_PERS_DATA_EFFDT GVT_STEP: VARCHAR2(2) GVT_RTND_PAY_PLAN: VARCHAR2(2) GVT_RTND_SAL_PLAN: VARCHAR2(4) EMPLID: VARCHAR2(11) GVT_RTND_GRADE: VARCHAR2(3) EFFDT: DATE GVT_RTND_STEP: NUMBER MAR_STATUS: VARCHAR2(1) GVT_RTND_GVT_STEP: VARCHAR2(2) SMOKER: VARCHAR2(1) GVT_PAY_BASIS: VARCHAR2(2) PS_PERSONAL_DT_FST PER_TYPE: VARCHAR2(1) GVT_COMPRATE: NUMBER(18,6) MAR_STATUS_DT: DATE GVT_LOCALITY_ADJ: NUMBER(7,2) EMPLID: PER.EMPLID SEX: VARCHAR2(1) GVT_BIWEEKLY_RT: NUMBER(9,2) PER_STATUS: PER.PER_STATUS AGE_STATUS: VARCHAR2(1) GVT_DAILY_RT: NUMBER(9,2) PER_TYPE: PDE.PER_TYPE HIGHEST_EDUC_LVL: VARCHAR2(2) GVT_HRLY_RT_NO_LOC: NUMBER(18,6) COUNTRY_NM_FORMAT: A.COUNTRY_NM_FORMAT FT_STUDENT: VARCHAR2(1) GVT_DLY_RT_NO_LOC: NUMBER(9,2) NAME: A.NAME LANG_CD: VARCHAR2(3) GVT_BW_RT_NO_LOC: NUMBER(9,2) NAME_INITIALS: A.NAME_INITIALS YEARS_OF_EXP: NUMBER(4,1) GVT_MNLY_RT_NO_LOC: NUMBER(18,3) NAME_PREFIX: A.NAME_PREFIX APPLID: VARCHAR2(11) GVT_ANNL_RT_NO_LOC: NUMBER(18,3) NAME_SUFFIX: A.NAME_SUFFIX APP_DT: DATE GVT_XFER_FROM_AGCY: VARCHAR2(2) NAME_ROYAL_PREFIX: A.NAME_ROYAL_PREFIX ALTER_EMPLID: VARCHAR2(11) GVT_XFER_TO_AGCY: VARCHAR2(2) NAME_ROYAL_SUFFIX: A.NAME_ROYAL_SUFFIX BILINGUALISM_CODE: VARCHAR2(1) PS_FAST_SCRTY_2 GVT_RETIRE_PLAN: VARCHAR2(1) NAME_TITLE: A.NAME_TITLE HEALTH_CARE_NBR: VARCHAR2(12) GVT_ANN_IND: VARCHAR2(1) LAST_NAME_SRCH: A.LAST_NAME_SRCH HEALTH_CARE_STATE: VARCHAR2(6) GVT_FEGLI: VARCHAR2(2) FIRST_NAME_SRCH: A.FIRST_NAME_SRCH GUARDIAN_CHE: VARCHAR2(40) SETID: VARCHAR2(5) GVT_FEGLI_LIVING: VARCHAR2(1) LAST_NAME: A.LAST_NAME MILIT_SITUATN_ESP: VARCHAR2(3) DEPTID: VARCHAR2(10) GVT_LIVING_AMT: NUMBER FIRST_NAME: A.FIRST_NAME SOC_SEC_AFF_DT: DATE ROWSECCLASS: VARCHAR2(30) GVT_ANNUITY_OFFSET: NUMBER MIDDLE_NAME: A.MIDDLE_NAME GVT_CRED_MIL_SVCE: VARCHAR2(4) ACCESS_CD: VARCHAR2(1) GVT_CSRS_FROZN_SVC: VARCHAR2(4) SECOND_LAST_NAME: A.SECOND_LAST_NAME GVT_MILITARY_COMP: VARCHAR2(1) GVT_PREV_RET_COVRG: VARCHAR2(1) SECOND_LAST_SRCH: A.SECOND_LAST_SRCH GVT_MIL_GRADE: VARCHAR2(3) GVT_FERS_COVERAGE: VARCHAR2(1) NAME_AC: A.NAME_AC GVT_MIL_RESRVE_CAT: VARCHAR2(1) GVT_TYPE_OF_APPT: VARCHAR2(2) PREF_FIRST_NAME: A.PREF_FIRST_NAME GVT_MIL_SEP_RET: VARCHAR2(1) GVT_POI: VARCHAR2(4) PARTNER_LAST_NAME: A.PARTNER_LAST_NAME GVT_MIL_SVCE_END: DATE GVT_POSN_OCCUPIED: VARCHAR2(1) PARTNER_ROY_PREFIX: A.PARTNER_ROY_PREFIX GVT_MIL_SVCE_START: DATE GVT_CONT_EMPLID: VARCHAR2(11) LAST_NAME_PREF_NLD: A.LAST_NAME_PREF_NLD GVT_MIL_VERIFY: VARCHAR2(1) GVT_ROUTE_NEXT: VARCHAR2(11) ORIG_HIRE_DT: PER.ORIG_HIRE_DT GVT_PAR_NBR_LAST: NUMBER GVT_CHANGE_FLAG: VARCHAR2(1) SEX: PDE.SEX GVT_UNIF_SVC_CTR: VARCHAR2(1) GVT_TSP_UPD_IND: VARCHAR2(1) AGE_STATUS: PDE.AGE_STATUS GVT_VET_PREF_APPT: VARCHAR2(1) GVT_PI_UPD_IND: VARCHAR2(1) MAR_STATUS: PDE.MAR_STATUS GVT_VET_PREF_RIF: VARCHAR2(1) GVT_SF52_NBR: VARCHAR2(10) MAR_STATUS_DT: PDE.MAR_STATUS_DT GVT_CHANGE_FLAG: VARCHAR2(1) GVT_S113G_CEILING: VARCHAR2(1) BIRTHDATE: PER.BIRTHDATE GVT_DRAFT_STATUS: VARCHAR2(1) GVT_LEO_POSITION: VARCHAR2(1) BIRTHPLACE: PER.BIRTHPLACE GVT_YR_ATTAINED: DATE GVT_ANNUIT_COM_DT: DATE BIRTHCOUNTRY: PER.BIRTHCOUNTRY DISABLED_VET: VARCHAR2(1) GVT_BASIC_LIFE_RED: VARCHAR2(2) BIRTHSTATE: PER.BIRTHSTATE DISABLED: VARCHAR2(1) GVT_DED_PRORT_DT: DATE DT_OF_DEATH: PER.DT_OF_DEATH ETHNIC_GROUP: VARCHAR2(1) GVT_FEGLI_BASC_PCT: NUMBER(7,6) HIGHEST_EDUC_LVL: PDE.HIGHEST_EDUC_LVL GVT_DISABILITY_CD: VARCHAR2(2) GVT_FEGLI_OPT_PCT: NUMBER(7,6) FT_STUDENT: PDE.FT_STUDENT GRADE: VARCHAR2(3) GVT_FEHB_PCT: NUMBER(7,6) HIGHLY_COMP_EMPL_P: PER.HIGHLY_COMP_EMPL_P SAL_ADMIN_PLAN: VARCHAR2(4) GVT_SUB_AGENCY: VARCHAR2(2) HIGHLY_COMP_EMPL_C: PER.HIGHLY_COMP_EMPL_C GVT_CURR_AGCY_EMPL: VARCHAR2(1) GVT_RETRO_FLAG: VARCHAR2(1) US_WORK_ELIGIBILTY: PDE.US_WORK_ELIGIBILTY GVT_CURR_FED_EMPL: VARCHAR2(1) GVT_RETRO_DED_FLAG: VARCHAR2(1) MILITARY_STATUS: PDE.MILITARY_STATUS GVT_HIGH_PAY_PLAN: VARCHAR2(2) GVT_RETRO_JOB_FLAG: VARCHAR2(1) CITIZEN_PROOF1: PDE.CITIZEN_PROOF1 GVT_HIGH_GRADE: VARCHAR2(3) GVT_RETRO_BSE_FLAG: VARCHAR2(1) CITIZEN_PROOF2: PDE.CITIZEN_PROOF2 GVT_PREV_AGCY_EMPL: VARCHAR2(1) GVT_OTH_PAY_CHG: VARCHAR2(1) SMOKER: PDE.SMOKER GVT_PREV_FED_EMPL: VARCHAR2(1) GVT_DETL_POSN_NBR: VARCHAR2(8) MEDICARE_ENTLD_DT: PDE.MEDICARE_ENTLD_DT GVT_SEP_INCENTIVE: VARCHAR2(1) ANNL_BEN_BASE_OVRD: VARCHAR2(1) SMOKER_DT: PDE.SMOKER_DT GVT_SEP_INCENT_DT: DATE BENEFIT_PROGRAM: VARCHAR2(3) BILINGUALISM_CODE: PDE.BILINGUALISM_CODE GVT_TENURE: VARCHAR2(1) UPDATE_PAYROLL: VARCHAR2(1) HEALTH_CARE_NBR: PDE.HEALTH_CARE_NBR GVT_PAY_PLAN: VARCHAR2(2) GVT_PAY_PLAN: VARCHAR2(2) HEALTH_CARE_STATE: PDE.HEALTH_CARE_STATE BARG_UNIT: VARCHAR2(4) GVT_PAY_FLAG: VARCHAR2(1) GUARDIAN_CHE: PDE.GUARDIAN_CHE ENTRY_DT_FRA: DATE GVT_NID_CHANGE: VARCHAR2(1) MILITARY_STAT_GER: PDE.MILITARY_STAT_GER MILIT_SITUATN_FRA: VARCHAR2(3) SUPERVISOR_ID: VARCHAR2(11) EXPCTD_MILITARY_DT: PDE.EXPCTD_MILITARY_DT CPAMID: VARCHAR2(6) APPT_TYPE: VARCHAR2(1) HR_RESPONSIBLE_ID: PDE.HR_RESPONSIBLE_ID MILITARY_STAT_GER: VARCHAR2(1) MAIN_APPT_NUM_JPN: NUMBER ENTRY_DT_FRA: PDE.ENTRY_DT_FRA EXPCTD_MILITARY_DT: DATE POSITION_OVERRIDE: VARCHAR2(1) MILIT_SITUATN_FRA: PDE.MILIT_SITUATN_FRA HR_RESPONSIBLE_ID: VARCHAR2(11) POSN_CHANGE_RECORD: VARCHAR2(1) CPAMID: PDE.CPAMID MILITARY_STAT_ITA: VARCHAR2(1) EMPL_STATUS: VARCHAR2(1) HONSEKI_JPN: PDE.HONSEKI_JPN MILITARY_TYPE_ITA: VARCHAR2(2) ACTION: VARCHAR2(3) MILITARY_STAT_ITA: PDE.MILITARY_STAT_ITA MILITARY_RANK_ITA: VARCHAR2(50) ACTION_DT: DATE MILITARY_TYPE_ITA: PDE.MILITARY_TYPE_ITA MILITARY_END_ITA: DATE ACTION_REASON: VARCHAR2(3) MILITARY_RANK_ITA: PDE.MILITARY_RANK_ITA HONSEKI_JPN: VARCHAR2(2) LOCATION: VARCHAR2(10) MILITARY_END_ITA: PDE.MILITARY_END_ITA US_WORK_ELIGIBILTY: VARCHAR2(1) TAX_LOCATION_CD: VARCHAR2(10) MILIT_SITUATN_ESP: PDE.MILIT_SITUATN_ESP MILITARY_STATUS: VARCHAR2(1) JOB_ENTRY_DT: DATE SOC_SEC_AFF_DT: PDE.SOC_SEC_AFF_DT CITIZEN_PROOF1: VARCHAR2(10) DEPT_ENTRY_DT: DATE LANG_CD: PDE.LANG_CD CITIZEN_PROOF2: VARCHAR2(10) POSITION_ENTRY_DT: DATE YEARS_OF_EXP: PDE.YEARS_OF_EXP MEDICARE_ENTLD_DT: DATE SHIFT: VARCHAR2(1) APPLID: PDE.APPLID SMOKER_DT: DATE REG_TEMP: VARCHAR2(1) APP_DT: PDE.APP_DT FP_ACTION_2: VARCHAR2(3) FULL_PART_TIME: VARCHAR2(1) GVT_CRED_MIL_SVCE: PDE.GVT_CRED_MIL_SVCE ACTION_REASON: VARCHAR2(3) COMPANY: VARCHAR2(3) GVT_MILITARY_COMP: PDE.GVT_MILITARY_COMP FP_ACTION_REQ: VARCHAR2(1) PAYGROUP: VARCHAR2(3) GVT_MIL_GRADE: PDE.GVT_MIL_GRADE FP_SUPDOC_REQ: VARCHAR2(1) BAS_GROUP_ID: VARCHAR2(3) GVT_MIL_RESRVE_CAT: PDE.GVT_MIL_RESRVE_CAT LAST_UPDATE_DATE: DATE ELIG_CONFIG1: VARCHAR2(10) GVT_MIL_SEP_RET: PDE.GVT_MIL_SEP_RET ELIG_CONFIG2: VARCHAR2(10) GVT_MIL_SVCE_END: PDE.GVT_MIL_SVCE_END ELIG_CONFIG3: VARCHAR2(10) GVT_MIL_SVCE_START: PDE.GVT_MIL_SVCE_START ELIG_CONFIG4: VARCHAR2(10) GVT_MIL_VERIFY: PDE.GVT_MIL_VERIFY ELIG_CONFIG5: VARCHAR2(10) GVT_PAR_NBR_LAST: PDE.GVT_PAR_NBR_LAST ELIG_CONFIG6: VARCHAR2(10) GVT_UNIF_SVC_CTR: PDE.GVT_UNIF_SVC_CTR ELIG_CONFIG7: VARCHAR2(10) GVT_VET_PREF_APPT: PDE.GVT_VET_PREF_APPT ELIG_CONFIG8: VARCHAR2(10) GVT_VET_PREF_RIF: PDE.GVT_VET_PREF_RIF ELIG_CONFIG9: VARCHAR2(10) PS_PERSON BEN_STATUS: VARCHAR2(4) GVT_CHANGE_FLAG: PDE.GVT_CHANGE_FLAG GVT_DRAFT_STATUS: PDE.GVT_DRAFT_STATUS PS_B_FAST_EMP_QRY BAS_ACTION: VARCHAR2(3) GVT_YR_ATTAINED: PDE.GVT_YR_ATTAINED COBRA_ACTION: VARCHAR2(3) EMPLID: VARCHAR2(11) EMPL_TYPE: VARCHAR2(1) DISABLED_VET: PDE.DISABLED_VET PER_STATUS: VARCHAR2(1) EMPLID: A.EMPLID DISABLED: PDE.DISABLED EMPL_RCD: JOB.EMPL_RCD HOLIDAY_SCHEDULE: VARCHAR2(6) BIRTHDATE: DATE STD_HOURS: NUMBER(6,2) ETHNIC_GROUP: PDE.ETHNIC_GROUP BIRTHPLACE: VARCHAR2(30) ROWSECCLASS: SEC.ROWSECCLASS GVT_DISABILITY_CD: PDE.GVT_DISABILITY_CD ACCESS_CD: SEC.ACCESS_CD STD_HRS_FREQUENCY: VARCHAR2(5) BIRTHCOUNTRY: VARCHAR2(3) OFFICER_CD: VARCHAR2(1) GRADE: PDE.GRADE BIRTHSTATE: VARCHAR2(6) NAME: B.NAME SAL_ADMIN_PLAN: PDE.SAL_ADMIN_PLAN LAST_NAME_SRCH: B.LAST_NAME_SRCH EMPL_CLASS: VARCHAR2(3) DT_OF_DEATH: DATE SAL_ADMIN_PLAN: VARCHAR2(4) GVT_CURR_AGCY_EMPL: PDE.GVT_CURR_AGCY_EMPL ORIG_HIRE_DT: DATE NAME_AC: B.NAME_AC GVT_CURR_FED_EMPL: PDE.GVT_CURR_FED_EMPL PER_STATUS: A.PER_STATUS GRADE: VARCHAR2(3) HIGHLY_COMP_EMPL_C: VARCHAR2(1) GRADE_ENTRY_DT: DATE GVT_HIGH_PAY_PLAN: PDE.GVT_HIGH_PAY_PLAN HIGHLY_COMP_EMPL_P: VARCHAR2(1) GVT_HIGH_GRADE: PDE.GVT_HIGH_GRADE STEP: NUMBER GVT_PREV_AGCY_EMPL: PDE.GVT_PREV_AGCY_EMPL STEP_ENTRY_DT: DATE GVT_PREV_FED_EMPL: PDE.GVT_PREV_FED_EMPL GL_PAY_TYPE: VARCHAR2(6) GVT_SEP_INCENTIVE: PDE.GVT_SEP_INCENTIVE ACCT_CD: VARCHAR2(25) GVT_SEP_INCENT_DT: PDE.GVT_SEP_INCENT_DT EARNS_DIST_TYPE: VARCHAR2(1) GVT_TENURE: PDE.GVT_TENURE COMP_FREQUENCY: VARCHAR2(5) GVT_PAY_PLAN: PDE.GVT_PAY_PLAN COMPRATE: NUMBER(18,6) BARG_UNIT: PDE.BARG_UNIT CHANGE_AMT: NUMBER(18,6) ALTER_EMPLID: PDE.ALTER_EMPLID CHANGE_PCT: NUMBER(6,3) ANNUAL_RT: NUMBER(18,3) MONTHLY_RT: NUMBER(18,3) DAILY_RT: NUMBER(18,3) HOURLY_RT: NUMBER(18,6) ANNL_BENEF_BASE_RT: NUMBER(18,3) SHIFT_RT: NUMBER(18,6) SHIFT_FACTOR: NUMBER(4,3) CURRENCY_CD: VARCHAR2(3) BUSINESS_UNIT: VARCHAR2(5) PS_PERSONAL_DTA_VW SETID_DEPT: VARCHAR2(5) SETID_JOBCODE: VARCHAR2(5) EMPLID: PS_PERSON_NAME.EMPLID SETID_LOCATION: VARCHAR2(5) NAME: PS_PERSON_NAME.NAME SETID_SALARY: VARCHAR2(5) REG_REGION: VARCHAR2(5) DIRECTLY_TIPPED: VARCHAR2(1) FLSA_STATUS: VARCHAR2(1) EEO_CLASS: VARCHAR2(1) FUNCTION_CD: VARCHAR2(2) TARIFF_GER: VARCHAR2(2) TARIFF_AREA_GER: VARCHAR2(3) PERFORM_GROUP_GER: VARCHAR2(2) LABOR_TYPE_GER: VARCHAR2(1) SPK_COMM_ID_GER: VARCHAR2(9) HOURLY_RT_FRA: VARCHAR2(3) PS_NAMES ACCDNT_CD_FRA: VARCHAR2(1) PS_PERSON_NAME VALUE_1_FRA: VARCHAR2(5) VALUE_2_FRA: VARCHAR2(5) EMPLID: VARCHAR2(11) EMPLID: A.EMPLID VALUE_3_FRA: VARCHAR2(5) NAME_TYPE: VARCHAR2(3) COUNTRY_NM_FORMAT: A.COUNTRY_NM_FORMAT VALUE_4_FRA: VARCHAR2(5) EFFDT: DATE NAME: A.NAME VALUE_5_FRA: VARCHAR2(5) NAME_PREFIX: VARCHAR2(4) NAME_INITIALS: A.NAME_INITIALS CTG_RATE: NUMBER NAME_SUFFIX: VARCHAR2(15) NAME_PREFIX: A.NAME_PREFIX PAID_HOURS: NUMBER(6,2) LAST_NAME_SRCH: VARCHAR2(30) NAME_SUFFIX: A.NAME_SUFFIX PAID_FTE: NUMBER(7,6) FIRST_NAME_SRCH: VARCHAR2(30) NAME_ROYAL_PREFIX: A.NAME_ROYAL_PREFIX PAID_HRS_FREQUENCY: VARCHAR2(5) FIRST_NAME: VARCHAR2(30) NAME_ROYAL_SUFFIX: A.NAME_ROYAL_SUFFIX UNION_FULL_PART: VARCHAR2(1) MIDDLE_NAME: VARCHAR2(30) NAME_TITLE: A.NAME_TITLE UNION_POS: VARCHAR2(1) LAST_NAME: VARCHAR2(30) LAST_NAME: A.LAST_NAME MATRICULA_NBR: NUMBER COUNTRY_NM_FORMAT: VARCHAR2(3) LAST_NAME_SRCH: A.LAST_NAME_SRCH SOC_SEC_RISK_CODE: VARCHAR2(3) NAME_INITIALS: VARCHAR2(6) FIRST_NAME_SRCH: A.FIRST_NAME_SRCH UNION_FEE_AMOUNT: NUMBER(8,2) NAME_ROYAL_PREFIX: VARCHAR2(15) FIRST_NAME: A.FIRST_NAME UNION_FEE_START_DT: DATE NAME_ROYAL_SUFFIX: VARCHAR2(15) MIDDLE_NAME: A.MIDDLE_NAME UNION_FEE_END_DT: DATE NAME: VARCHAR2(50) SECOND_LAST_NAME: A.SECOND_LAST_NAME EXEMPT_JOB_LBR: VARCHAR2(1) NAME_TITLE: VARCHAR2(30) SECOND_LAST_SRCH: A.SECOND_LAST_SRCH EXEMPT_HOURS_MONTH: NUMBER SECOND_LAST_NAME: VARCHAR2(30) NAME_AC: A.NAME_AC WRKS_CNCL_FUNCTION: VARCHAR2(1) SECOND_LAST_SRCH: VARCHAR2(30) PREF_FIRST_NAME: A.PREF_FIRST_NAME INTERCTR_WRKS_CNCL: VARCHAR2(1) NAME_AC: VARCHAR2(50) PARTNER_LAST_NAME: A.PARTNER_LAST_NAME CURRENCY_CD1: VARCHAR2(3) PREF_FIRST_NAME: VARCHAR2(30) PARTNER_ROY_PREFIX: A.PARTNER_ROY_PREFIX PAY_UNION_FEE: VARCHAR2(1) PARTNER_LAST_NAME: VARCHAR2(30) LAST_NAME_PREF_NLD: A.LAST_NAME_PREF_NLD UNION_CD: VARCHAR2(3) PARTNER_ROY_PREFIX: VARCHAR2(15) NAME_TYPE: A.NAME_TYPE BARG_UNIT: VARCHAR2(4) LAST_NAME_PREF_NLD: VARCHAR2(1) ASOFDATE: A.EFFDT UNION_SENIORITY_DT: DATE ENTRY_DATE: DATE LABOR_AGREEMENT: VARCHAR2(6) EMPL_CTG: VARCHAR2(6) EMPL_CTG_L1: VARCHAR2(6) EMPL_CTG_L2: VARCHAR2(6) SETID_LBR_AGRMNT: VARCHAR2(5) GP_PAYGROUP: VARCHAR2(10) GP_DFLT_ELIG_GRP: VARCHAR2(1) GP_ELIG_GRP: VARCHAR2(10) GP_DFLT_CURRTTYP: VARCHAR2(1) CUR_RT_TYPE: VARCHAR2(5) GP_DFLT_EXRTDT: VARCHAR2(1) GP_ASOF_DT_EXG_RT: VARCHAR2(1) ADDS_TO_FTE_ACTUAL: VARCHAR2(1) CLASS_INDC: VARCHAR2(1) ENCUMB_OVERRIDE: VARCHAR2(1) FICA_STATUS_EE: VARCHAR2(1) FTE: NUMBER(7,6) PRORATE_CNT_AMT: VARCHAR2(1) PAY_SYSTEM_FLG: VARCHAR2(2) BORDER_WALKER: VARCHAR2(1) LUMP_SUM_PAY: VARCHAR2(1) CONTRACT_NUM: VARCHAR2(25) JOB_INDICATOR: VARCHAR2(1) WRKS_CNCL_ROLE_CHE: VARCHAR2(30) BENEFIT_SYSTEM: VARCHAR2(2) WORK_DAY_HOURS: NUMBER(6,2) REPORTS_TO: VARCHAR2(8) FORCE_PUBLISH: DATE JOB_DATA_SRC_CD: VARCHAR2(3) ESTABID: VARCHAR2(12) PRIMARY_JOB: VARCHAR2(1) BOCES_TERM_JOBS: VARCHAR2(1) BOCES_TRM_JOB_PROC: VARCHAR2(1) BOCES_CIVIL_SRV: VARCHAR2(6) 15
  16. 16. So, I have to check view PS_PERSON_NAME and PS_FERSONAL_DT_FST first. ** Please find the detail DDL of those views on Appendix. [Dennis: ok] View PS_PERSON_NAME Built on table PS_NAMES, key columns of the table: emplid, name_type, effdt Column emplid – means employee id. It is unique and not null for any employee. On PS_NAME table, one EMPLID may come with different NAME_TYPE and Effdt. View PS_PERSON_NAME returns the NAME_TYPE = ‘PRI’ and max(EFFDT) for each EMPLID. EMPLID acts like the key of view PS_PERSON_NAME View PS_ERSONAL_DT_FST Built on table PS_NAME, PS_PERSON (key: emplid) and PS_PERS_DATA_EFFDT (key: emplid, effdt). View returns PS_PERSON.EMPLID (key of PS_PERSON); On the where clause: Table PS_PERS_DATA_EFFDT join with PS_PERSON, with EMPLID and max(effdt) of a range date –- which return unique result; And Table PS_NAME, restricted NAME_TYPE = ‘PRI’ and max(EFFDT) of a range date, with EMPLID column, EMPLID also can act as the key now, and join with EMPLID of PS_PERSON. Now, we can say that EMPLID acts like the key of view PS_PERSONAL_DT_FST too. PS_B_FAST_EMP_QRY Built on table PS_JOB (key: emplid, emp_rcd, effdt and effseq), table PS_FAST_SCRTY_2 (key: setid, deptid, rowsecclass); Table PS_PERSPN (key: emplid), and view PS_PERSONAL_DT_FST. On where clause of this view, join condition does not cover all key columns of all involved tables and view. It returns a cartesian production of (EMPLID, EMP_RCD) x ROWSECCLASS The key of view would be (EMPLID, EMP_RCD), ROWSECCLASS PS_PERSONAL_DTA_VW Built on view PS_PERSON_NAME, and EMPLID is also acts as the key of result PS_B_FAST_PERS_QRY Built on Tables PS_JOB and PS_FAST_SCRTY_2; and view PS_PERSONAL_DT_FST On where clause of this view, join condition does not cover all key columns of all involved tables and view. It returns a cartesian production of EMPLID x ROWSECCLASS The key of view would be EMPLID , ROWSECCLASS Now, (after a coffee break, of course) I can start to analyze the problem query now. On the SELECT clause, the selected columns do not cover all key columns of table PS_JOB. Column EFFSEQ missed. But on the WHERE clause: AND A.EFFSEQ = (SELECT MAX(A_ES.EFFSEQ) FROM PS_JOB A_ES WHERE A.EMPLID = A_ES.EMPLID AND A.EMPL_RCD = A_ES.EMPL_RCD AND A.EFFDT = A_ES.EFFDT) Guaranteed that selected key columns of table PS_JOB return unique result from PS_JOB; 16
  17. 17. PS_FAST_EMP_QRY, because of line AND A1.ROWSECCLASS = 'CPHR7030' , EMPLID becomes a key and join with PS_JOB; PS_B_FAST_PERS_QRY, because of line AND A1.ROWSECCLASS = 'CPHR7030' , EMPLID becomes a key and join with PS_PERSONAL_DTA_VW; PS_ERSONAL_DATA_VW, joins with PS_JOB on its key column EMPLID. We can say it now, The SELECT statement can return the same result without DISTINCT. Result: With DISTINCT: User ran over 5 hours without any data returned. User session was killed by DBA. I also re-ran the same query over 3 hours without any data returned. After DISTINCT removed: 1 min 34.94 seconds! [Dennis: Wow, that’s awesome!] Logs: 20283 rows selected. Elapsed: 00:01:34.94 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=59 Card=1 Bytes=135) 1 0 NESTED LOOPS (Cost=59 Card=1 Bytes=135) 2 1 NESTED LOOPS (Cost=59 Card=1 Bytes=117) 3 2 NESTED LOOPS (Cost=56 Card=1 Bytes=92) 4 3 NESTED LOOPS (Cost=54 Card=1 Bytes=77) 5 4 NESTED LOOPS (Cost=54 Card=1 Bytes=72) 6 5 NESTED LOOPS (Cost=52 Card=1 Bytes=55) 7 6 VIEW OF 'PS_B_FAST_PERS_QRY' (Cost=49 Card=1 B ytes=24) 8 7 SORT (UNIQUE) (Cost=49 Card=1 Bytes=76) 9 8 FILTER 10 9 NESTED LOOPS (Cost=15 Card=1 Bytes=76) 11 10 NESTED LOOPS (Cost=14 Card=1 Bytes=57) 12 11 NESTED LOOPS (Cost=11 Card=1 Bytes=32) 13 12 NESTED LOOPS (Cost=7 Card=2 Bytes=40) 14 13 INDEX (FAST FULL SCAN) OF 'PS_NAMES' (UNIQUE) (Cost=7 Card=2 Bytes=30) 15 13 INDEX (UNIQUE SCAN) OF 'PS_PERSON' (UNIQUE) 16 12 INDEX (RANGE SCAN) OF 'PS_PERS_DAT A_EFFDT' (UNIQUE) (Cost=2 Card=1 Bytes=12) 17 16 SORT (AGGREGATE) 18 17 FILTER 19 18 INDEX (RANGE SCAN) OF 'PS_PERS_DATA_EFFDT' (UNIQUE) (Cost=2 Card=1 Bytes=12) 20 18 SORT (AGGREGATE) 21 20 FIRST ROW (Cost=2 Card=1 Bytes=12) 17
  18. 18. 22 21 INDEX (RANGE SCAN (MIN/MAX)) OF 'PS_PERS_DATA_EFFDT' (UNIQUE) (Cost=2 Card=13441) 23 11 TABLE ACCESS (BY INDEX ROWID) OF 'PS_JOB' (Cost=3 Card=1 Bytes=25) 24 23 INDEX (RANGE SCAN) OF 'PSAJOB' (NON-UNIQUE) (Cost=2 Card=1) 25 24 SORT (AGGREGATE) 26 25 FIRST ROW (Cost=2 Card=1 Bytes=14) 27 26 INDEX (RANGE SCAN (MIN/MAX))OF 'PSAJOB' (NON- UNIQUE) (Cost=2 Card=87857) 28 24 SORT (AGGREGATE) 29 28 FIRST ROW (Cost=2 Card=1 Bytes=16) 30 29 INDEX (RANGE SCAN (MIN/MAX))OF 'PSAJOB' (NON- UNIQUE) (Cost=2 Card=87857) 31 10 TABLE ACCESS (BY INDEX ROWID) OF 'PS_FAST_SCRTY_2' (Cost=1 Card=1 Bytes=19) 32 31 INDEX (UNIQUE SCAN) OF 'PS_FAST_SCRTY_2' (UNIQUE) 33 9 SORT (AGGREGATE) 34 33 FILTER 35 34 INDEX (RANGE SCAN) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=1 Bytes=15) 36 34 SORT (AGGREGATE) 37 36 FIRST ROW (Cost=2 Card=1 Bytes=15) 38 37 INDEX (RANGE SCAN (MIN/MAX)) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=15179) 39 6 TABLE ACCESS (BY INDEX ROWID) OF 'PS_NAMES' (Cost=3 Card=1 Bytes=31) 40 39 INDEX (RANGE SCAN) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=1) 41 40 SORT (AGGREGATE) 42 41 FILTER 43 42 INDEX (RANGE SCAN) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=1 Bytes=15) 44 42 SORT (AGGREGATE) 45 44 FIRST ROW (Cost=2 Card=1 Bytes=15) 46 45 INDEX (RANGE SCAN (MIN/MAX)) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=15179) 47 5 INDEX (RANGE SCAN) OF 'PSBJOB' (NON-UNIQUE) (Cost=2 Card=1 Bytes=17) 48 47 SORT (AGGREGATE) 49 48 FIRST ROW (Cost=2 Card=1 Bytes=14) 50 49 INDEX (RANGE SCAN (MIN/MAX)) OF 'PSAJOB' (NON-UNIQUE) (Cost=2 Card=87857) 51 47 SORT (AGGREGATE) 52 51 FIRST ROW (Cost=2 Card=1 Bytes=16) 53 52 INDEX (RANGE SCAN (MIN/MAX)) OF 'PSAJOB' (NON-UNIQUE) (Cost=2 Card=87857) 54 4 INDEX (UNIQUE SCAN) OF 'PS_PERSON' (UNIQUE) 55 3 INDEX (RANGE SCAN) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=1 Bytes=15) 56 55 SORT (AGGREGATE) 57 56 FILTER 58 57 INDEX (RANGE SCAN) OF 'PS_NAMES' (UNIQUE) (Cost=2 Card=1 Bytes=15) 18
  19. 19. 59 57 SORT (AGGREGATE) 60 59 FIRST ROW (Cost=2 Card=1 Bytes=15) 61 60 INDEX (RANGE SCAN (MIN/MAX)) OF 'PS_NAMES'(UNIQUE) (Cost=2 Card=15179) 62 2 TABLE ACCESS (BY INDEX ROWID) OF 'PS_JOB' (Cost=3 Card=1 Bytes=25) 63 62 INDEX (RANGE SCAN) OF 'PSAJOB' (NON-UNIQUE) (Cost=2 Card=1) 64 63 SORT (AGGREGATE) 65 64 FIRST ROW (Cost=2 Card=1 Bytes=14) 66 65 INDEX (RANGE SCAN (MIN/MAX)) OF 'PSAJOB' (NON-UNIQUE) (Cost=2 Card=87857) 67 63 SORT (AGGREGATE) 68 67 FIRST ROW (Cost=2 Card=1 Bytes=16) 69 68 INDEX (RANGE SCAN (MIN/MAX)) OF 'PSAJOB' (NON-UNIQUE) (Cost=2 Card=87857) 70 1 INDEX (UNIQUE SCAN) OF 'PS_FAST_SCRTY_2' (UNIQUE) Statistics ---------------------------------------------------------- 42 recursive calls 0 db block gets 460815 consistent gets 4367 physical reads 0 redo size 856878 bytes sent via SQL*Net to client 15527 bytes received via SQL*Net from client 1354 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 20283 rows processed Testing run on Microsoft SQL Server: SQL text: SELECT DISTINCT B.NAME, A.EMPLID, A.EMPL_RCD, A.EFFDT, A.EMPL_STATUS FROM PS_JOB A, PS_B_FAST_EMP_QRY A1, PS_PERSONAL_DTA_VW B, PS_B_FAST_PERS_QRY B1 WHERE A.EMPLID = A1.EMPLID AND A.EMPL_RCD = A1.EMPL_RCD AND A1.ROWSECCLASS = 'CPHR7030' AND B.EMPLID = B1.EMPLID AND B1.ROWSECCLASS = 'CPHR7030' AND ( A.EFFDT = (SELECT MAX(A_ED.EFFDT) FROM PS_JOB A_ED WHERE A.EMPLID = A_ED.EMPLID AND A.EMPL_RCD = A_ED.EMPL_RCD AND A_ED.EFFDT <= '2005-12-02') AND A.EFFSEQ = (SELECT MAX(A_ES.EFFSEQ) FROM PS_JOB A_ES WHERE A.EMPLID = A_ES.EMPLID AND A.EMPL_RCD = A_ES.EMPL_RCD AND A.EFFDT = A_ES.EFFDT) AND A.EMPLID = B.EMPLID ) With “DISTINCT”: 20283 rows fetched. Execution time: 06:37 19
  20. 20. Without “DISTINCT”: 20283 rows fetched. Execution time: 00:25 900 800 700 Throughput (rows/sec) 600 500 400 300 200 100 0 DISTINCT without DISTINCT Fetch 20283 rows on MS SQL Server Figure case 2.1 Throughput (rows/sec) of a query with “SELECT DISTINCT/SELECT”. Compare the batch size of 20283 rows FETCHED with/without “DISTINCT”. After I removed “distinct” the query throughput is improved 15.88 times. Conclusion: Minimizing DISTINCT in the query can improves the performance and reduces the response time. 20
  21. 21. Case 3: Query Tuning (Ref. Chapter 4.6) Scenario: Our Peoplesoft HRMS programmer showed me the following query, and told me it never return any data to her after 30 minutes. She said, she did not miss any join condition; all join were on key column of tables; and it was just a very simple query. She did not understand what the problems were. Problem Query: SELECT a.emplid FROM ps_job a, ps_b_fast_emp_qry a1, ps_jobcode_tbl b, ps_personal_data c, ps_sal_grade_tbl d, ps_employment e WHERE a.emplid = a1.emplid AND a.empl_rcd = a1.empl_rcd AND a1.rowsecclass = 'PPALL' AND e.emplid = a1.emplid AND e.empl_rcd = a1.empl_rcd AND a.effdt = (SELECT max(a_ed.effdt) FROM ps_job a_ed WHERE a.emplid = a_ed.emplid AND a.empl_rcd = a_ed.empl_rcd AND a_ed.effdt <= SYSDATE) AND a.effseq =(SELECT max(a_es.effseq) FROM ps_job a_es WHERE a.emplid = a_es.emplid AND a.empl_rcd = a_es.empl_rcd AND a.effdt = a_es.effdt) AND a.setid_jobcode = b.setid AND b.jobcode = a.jobcode AND b.effdt = (SELECT max(b_ed.effdt) FROM ps_jobcode_tbl b_ed WHERE b.setid = b_ed.setid AND b.jobcode = b_ed.jobcode AND b_ed.effdt <= a.effdt) AND a.emplid = c.emplid AND d.effdt = (SELECT max(d_ed.effdt) FROM ps_sal_grade_tbl d_ed WHERE d.setid = d_ed.setid AND d.sal_admin_plan = d_ed.sal_admin_plan AND d.grade = d_ed.grade AND d_ed.effdt <= SYSDATE) AND a.setid_salary = d.setid AND a.sal_admin_plan = d.sal_admin_plan AND a.grade = d.grade AND a.emplid = e.emplid AND a.empl_rcd = e.empl_rcd Description of the involved tables and views in this query: There are 7 tables and 3 views involved in this query. Tables: ***********on FROM clause • PS_JOB, a big table with 217 columns and 87,857 rows 21
  22. 22. Key: emplid, emp_rcd, effdt and effseq. • PS_SAL_GRADE_TBL, 42 columns 1830 rows Key: setid, sal_admin_plan, grade and effdt • PS_EMPLOYMENT. 91 columns and 20291 rows Key: emplid, empl_rcd • PS_JOBCODE_TBL 126 columns and 830 rows Key: setid, jobcode, effdt ***********not on FROM clause • PS_FAST_SCRTY_2, 4 columns and 14,970 rows Key: setid, deptid and rowsecclass • PS_NAMES, 23 columns and 15,179 rows Key: emplid, name_type and effdt • PS_PERSON, 10 columns and 13,268 rows Key: emplid Views: ***********on FROM clause • PS_B_FAST_EMP_QRY is a view, built on 3 base tables and 1 view Tables: PS_JOB, PS_PERSON AND PS_FAST_SCRTY_2 View: PS_PERSON_NAME • PS_PERSONAL_DATA, built on 1 table table: PS_NAME ***********not on FROM clause • PS_PERSONAL_NAME Table: PS_NAME Query Tuning: This query looks similar as the one on Case 2, right? All our problem queries look similar. But they have different problem. 22

×