1 sql best coding practice in peopletools 7.x david kurtz go-faster consultancy ltd....

Post on 29-Mar-2015

219 Views

Category:

Documents

4 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

SQL Best Coding Practice in PeopleTools 7.x

David KurtzGo-Faster Consultancy Ltd.

david@go-faster.co.uk

www.go-faster.co.uk

2

Who are you?

• Familiar with SQL• not necessarily the DBA• Might be

– Application developer

– Team Leader

3

So Where is all the SQL?

• Views• Scrollxxx() PeopleCode• SQLExec() PeopleCode• Mass Change• Application Engine• PS/Query / Crystal• SQR• Stored Statements

4

Views

5

Scrollxxx() PeopleCode

6

SQLExec() PeopleCode

7

Mass Change

8

Application Engine

9

PS/Query / Crystal

10

SQR

11

Stored Statements

12

Simplicity

• As simple as possible• As complicated as necessary

• Data Model• Avoid excessive I/O

13

SQL

• Coding Standard• Implicit Type Conversion• Sorts• Indexes• Sub-queries

14

Coding Standards

• Be explicit– Make it readable

• Indent sub-queries and brackets

– Use table aliases• Lower parse time

• Less unexpected results without error messages

– Avoid implicit type conversion

– Avoid possible Y2K issue• Explicitly specify Y2K compliant date formats

15

Readability

CREATE TABLE PS_GEN_JOB_TBL(...) AS SELECT DISTINCT ...FROM PS_PERSONAL_DATA A, PS_JOB B, PS_PERS_NID ND,

PS_NID_TYPE_TBL NDTWHERE A.EMPLID=B.EMPLIDAND A.EMPLID=ND.EMPLIDAND B.EMPLID=ND.EMPLIDAND ND.NATIONAL_ID_TYPE=NDT.NATIONAL_ID_TYPEAND ( B.EFFDT>=%CURRENTDATEIN

OR ( B.EFFDT=( SELECT MAX(B2.EFFDT)FROM PS_JOB B2WHERE B2.EMPLID=B.EMPLID AND B2.EMPL_RCD#=B.EMPL_RCD# AND B2.EFFDT<=%CURRENTDATEIN)

AND B.EFFSEQ= (SELECT MAX(B3.EFFSEQ) FROM PS_JOB B3 WHERE B3.EMPLID=B.EMPLID AND B3.EMPL_RCD#=B.EMPL_RCD# AND B3.EFFDT=B.EFFDT)))

16

Minimum table aliases

SELECT COUNT(*)FROM PS_JOB BWHERE ( EFFDT=( SELECT MAX(B1.EFFDT)

FROM PS_JOB B1WHERE B.EMPLID=EMPLID AND B.EMPL_RCD#=EMPL_RCD# AND B.EFFDT<=%CURRENTDATEIN)

AND EFFSEQ= (SELECT MAX(B2.EFFSEQ) FROM PS_JOB B2WHERE B.EMPLID=EMPLID AND B.EMPL_RCD#=EMPL_RCD# AND B.EFFDT=EFFDT))

17

Maximum table aliases

SELECT COUNT(*)FROM PS_JOB BWHERE ( B.EFFDT=( SELECT MAX(B1.EFFDT)

FROM PS_JOB B1WHERE B1.EMPLID=B.EMPLID AND B1.EMPL_RCD#=B.EMPL_RCD# AND B1.EFFDT<=%CURRENTDATEIN)

AND B.EFFSEQ= (SELECT MAX(B2.EFFSEQ) FROM PS_JOB B2WHERE B2.EMPLID=B.EMPLID AND B2.EMPL_RCD#=B.EMPL_RCD# AND B2.EFFDT=B.EFFDT))

18

Wrong table alias

SELECT COUNT(*)FROM PS_JOB BWHERE ( EFFDT=( SELECT MAX(B1.EFFDT)

FROM PS_JOB B1WHERE B.EMPLID=EMPLID AND B.EMPL_RCD#=EMPL_RCD# AND B.EFFDT<=%CURRENTDATEIN)

AND EFFSEQ= (SELECT MAX(B2.EFFSEQ) FROM PS_JOB B2WHERE B2.EMPLID=EMPLID AND B2.EMPL_RCD#=EMPL_RCD# AND B2.EFFDT=EFFDT))

19

Implicit Type Conversion

SELECT *FROM PS_JOBWHERE EMPLID=8001

SELECT *FROM PS_JOBWHERE EMPLID=‘8001’

20

Implicit Type Conversion

SELECT *FROM PS_JOBWHERE EMPLID=8001

TABLE ACCESS (FULL) OF 'PS_JOB’

why did this not use the index?

SELECT *FROM PS_JOBWHERE EMPLID=‘8001’

INDEX (RANGE SCAN) OF 'PSAJOB' (NON-UNIQUE)

21

Implicit Type Conversion

SELECT *FROM PS_JOBWHERE EMPLID=8001

TABLE ACCESS (FULL) OF 'PS_JOB’

why did this not use the index?

SELECT *FROM PS_JOBWHERE TO_NUMBER(EMPLID)=8001

SELECT *FROM PS_JOBWHERE EMPLID=‘8001’

INDEX (RANGE SCAN) OF 'PSAJOB' (NON-UNIQUE)

22

Sorts

• Updating indexed columns• Distinct• Order by• Group by• Union -v- Union All

23

Indexes

• >~ 200 rows• <~ 10%

– Very rough guidelines

– Avoid updating indexed columns

– Sometimes, even very small tables, that fit in a single block can benefit from a suitable index.

24

Distinct

• Sorts whole select list• Can drive the join order of the tables• Avoid distinct & order by

– Order one way for the distinct

– Order another way for the order by

25

Distinct

SELECT DISTINCT A,B,C,DFROM tableORDER BY A,B,C

• ‘Order by’ clause is necessary– Update Mar 2009 – Up to Oracle 9i,DISTINCT and GROUP BY used a sort operation, so on non-partitioned tables the rows were returned in that order. In Oracle 10g these commands use a hash operation. If you want the rows in a particular order you should say so!

26

Distinct

• Instead of

SELECT DISTINCT

A,B,C,DFROM tableORDER BY A,C,B

• Do not rely on this

SELECT DISTINCT

A,C,B, DFROM table

27

Group by

• Instead of

SELECT A,B,C,SUM(D)

FROM tableGROUP BY A,B,CORDER BY A,C,B

• Do not rely on this

SELECT A,C,B,

SUM(D)FROM tableGROUP BY A,C,B

28

But if hash operation disabled

• Instead of

SELECT A,B,C,SUM(D)

FROM tableGROUP BY A,B,CORDER BY A,C,B

• Match the group and order clauses

SELECT A,C,B, SUM(D)

FROM tableGROUP BY A,C,BORDER A,C,B

29

Union -v- Union All

• Union– Each query is distinct, and so is sorted

• Hash operation possible in Oracle 10g

– Duplicates are eliminated

• Union All– One query followed by the next

30

Union -v- Union All

SELECT 1FROM dualUNIONSELECT 1FROM dual

• Returns

Dummy-----1

SELECT 1FROM dualUNION ALLSELECT 1FROM dual

• Returns

Dummy-----11

31

Union -v- Union All

SELECT 2FROM dualUNIONSELECT 1FROM dual

• Returns

Dummy-----12

SELECT 2FROM dualUNION ALLSELECT 1FROM dual

• Returns

Dummy-----21

32

Disabling Indexes

• Functions on columns• Index disabled

– TO_CHAR(column,’DD-MM-YYYY’) = :bind

• Index enabled– column = TO_DATE(:bind, ’DD-MM-YYYY’)

• Oracle syntax, generic principle

33

Use all indexed columns

• Specify all indexed columns– Cannot exact scan column unless exact scan all

previous columns

34

Use all indexed columns

SELECT …FROM PS_JOB BWHERE EMPLID = :1AND EFFSEQ = (SELECT MAX(EFFSEQ)

FROM PS_JOB B1WHERE B1.EMPLID = B.EMPLIDAND B1.EFFDT = B.EFFDT)

SELECT …FROM PS_JOB BWHERE EMPLID = :1AND EFFDT = (SELECT MAX(EFFSEQ)

FROM PS_JOB B1WHERE B1.EMPLID = B.EMPLIDAND B1.EMPL_RCD# = B.EMPL_RCD#AND B1.EFFDT = B.EFFDT)

35

High Water Marks (Oracle)

• Oracle specific• Delete -v- Truncate

DELETE FROM table;

TRUNCATE TABLE table;

– Full Scans - HWM

36

Sub-queries

• Correlated– executed once per parent row

– (because PeopleSoft recommend disabling _UNNEST_SUBQUERY from Oracle 9i).

• Not Correlated– executed once in advance

37

Sub-queries

– Correlated

DELETE FROM table1 t1WHERE EXISTS(

SELECT ‘x’FROM table2 t2WHERE t1.keycolumn = t2.keycolumn)

– Non-Correlated

DELETE FROM table1 t1WHERE t1.keycolumn IN(

SELECT t2.keycolumnFROM table2 t2)

38

Sub-queries (Oracle)

• Oracle specific

DELETE FROM table1 t1WHERE (t1.keycolumn1, t1.keycolumn2) IN(SELECT t2.keycolumn1, t2.keycolumn2FROM table2 t2)

39

ROWID (Oracle)

• Oracle specific• physical address of row

40

Sub-queries (Oracle)

• Oracle specific

DELETE FROM table1 t1WHERE t1.rowid IN(SELECT t1b.rowidFROM table1 t1b, table2 t2WHERE t1b.keycolumn1 = t2.keycolumn2AND t1b.keycoulmn2 = t2.keycolumn2)

41

Order of ‘From’ clause (Oracle)

• Oracle specific• Rule Based Optimiser

– backwards

• Cost Based Optimiser– doesn’t matter

• CBO + Ordered Hint– Forwards

– But use LEADING hint from 10g

42

Summary

• Lots of places to write SQL• Code should be

– efficient

– simple

– readable

– explicit

43

SQL Best Coding Practice in PeopleTools 7.x

David KurtzGo-Faster Consultancy Ltd.

david@go-faster.co.uk

www.go-faster.co.uk

top related