DB2 CURSOR
-
Upload
api-3701299 -
Category
Documents
-
view
49 -
download
3
Transcript of DB2 CURSOR
![Page 1: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/1.jpg)
![Page 2: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/2.jpg)
Existence check
Sometimes we need to check if a specific datum is in the table in order to decide what to do.
e.g. If it exists do “A” Else do “B”.
Datum - singular
Data - plural
![Page 3: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/3.jpg)
Existence check -BAD (1)Existence check -BAD (1)
SELECT DISTINCT 1INTO :HVFROM TABLEWHERE ….
1. If there is no index to satisfy the “WHERE”then we do tablespace scan and sort.
2. Even if we have an index, we may have duplicates
so we still invoke the sort.3. Even if we have unique index – it may be changed
in the future.4. SQL code may be copied, bad practice continues.
![Page 4: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/4.jpg)
Existence check –BAD (2)Existence check –BAD (2) SELECT COUNT(*)INTO :HVFROM TABLEWHERE ….
1. If there is no index to satisfy the “WHERE”then we do tablespace scan.
2. Even if we have index, we count all occurrences.
(It’s o.k. If we were asked to count all rows).
![Page 5: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/5.jpg)
Existence check – GOOD (3)Existence check – GOOD (3)
1. DECLARE CURSOR.(Optimize for 1 row with UR)
2. OPEN CURSOR.3. FETCH.4. CLOSE CURSOR.
1. Need to code 4 SQL statements.2. Looks cumbersome.3. Uses more resource then the next idea.
![Page 6: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/6.jpg)
Existence check – GOOD (4)Existence check – GOOD (4)
SELECT 1INTO :HVFROM TABLEWHERE ….
IF SQLCODE = +100 THEN “NOT_EXISTS”IF SQLCODE = 0 or SQLCODE = -811 THEN “EXISTS”.
1. Needs some documentation in the program.2. Don’t use any data returned by it.
![Page 7: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/7.jpg)
Internal secretInternal secret
• A A singletonsingleton select is done internally as a cursor ! select is done internally as a cursor !• Does not use cross memory calls as regular cursor.Does not use cross memory calls as regular cursor.• Internal code length is shorter then regular cursor.Internal code length is shorter then regular cursor.• DB2 builds a cursor read, internally, for the DB2 builds a cursor read, internally, for the
singleton select and does 1 or 2 fetch commands:singleton select and does 1 or 2 fetch commands:– If the 1st command finds nothing,If the 1st command finds nothing,
we get a sqlcode = +100. we get a sqlcode = +100.– If the 2nd command finds something,If the 2nd command finds something,
we get a sqlcode = -811.we get a sqlcode = -811.– Else we get the data and sqlcode = 0.Else we get the data and sqlcode = 0.
![Page 8: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/8.jpg)
Sub Select - BADSub Select - BAD
SELECT * FROM T1WHERE T1.CODE IN
(select T2.code
from T2 where T2.key = ‘X’)
1. Will cause tablespace scan on T1.2. DB2 may change this type of
sub select to Join (if possible).
![Page 9: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/9.jpg)
Do it as join -GOODDo it as join -GOOD
SELECT T1.* FROM T1 , T2WHERE T2.KEY = ‘X’AND T1.CODE=T2.CODE
![Page 10: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/10.jpg)
Sub Select - GOODSub Select - GOOD
SELECT * FROM T1WHERE T1.CODE NOT IN
(select T2.code from T2 where T2.key = ‘X’)
Can’t be done as a Join.
![Page 11: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/11.jpg)
Sub Select - GOODSub Select - GOOD
SELECT * FROM T1WHERE NOT EXISTS
(select 1 from T2 where T1.code=T2.code)
Can’t be done as a Join.
![Page 12: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/12.jpg)
Sub Select – BAD or GOOD ?Sub Select – BAD or GOOD ?
SELECT A1, A2, A3 FROM T1WHERE A1 = ?AND A2 =
(select max(A2) from T1)
![Page 13: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/13.jpg)
Use a cursor - BAD or GOOD ?Use a cursor - BAD or GOOD ?
DECLARE CRS1 CURSOR FORSELECT A1, A2, A3 FROM T1WHERE A1 = ?ORDER BY A2 DESCOPTIMIZE FOR 1 ROW
Open crs1; fetch crs1 into…. ; close crs1
![Page 14: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/14.jpg)
Statistics
Time CPU SQL Sorts Locks Rows
0.00392 0.00341 4 0 7 4 0.00625 0.00517 4 1 9 24
Sub-Select
Cursor
Assuming proper indexin both cases !!!
![Page 15: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/15.jpg)
Sub-Query vs. Cursor - ConclusionSub-Query vs. Cursor - Conclusion
• Assuming proper index:– If the command is used infrequently then we
can use the sub-query, otherwise – use the cursor.
• If no proper index exists:– The cursor will invoke sort on all the rows that
conform to the search criteria.– The sub-query will scan all rows for the
max/min value but will not sort.– Use the sub-query.
![Page 16: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/16.jpg)
Conclusion
Proper indexes can help
![Page 17: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/17.jpg)
Real life example (1)
SELECT * FROM MNTB.TVTNSDRA A WHERE A.LOT_NUMBER IN
(SELECT B.LOT_NUMBER FROM MNTB.TVTNITUR B WHERE UNIT = '638‘ AND
B.LOT_NUMBER = A.LOT_NUMBER);
Canceled after 23 minutes elapsed
Join column not 1st in index
![Page 18: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/18.jpg)
Real life example (2)
SELECT A.* FROM MNTB.TVTNSDRA A,
MNTB.TVTNITUR B WHERE UNIT = '638‘ AND
B.LOT_NUMBER = A.LOT_NUMBER WITH UR ;
Canceled after 14 minutes elapsed
Join column not 1st in index
![Page 19: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/19.jpg)
Real life example (3)
SELECT * FROM MNTB.TVTNSDRA A WHERE A.LOT_NUMBER IN
(SELECT DISTINCT B.LOT_NUMBER FROM MNTB.TVTNITUR B WHERE UNIT = '638‘) WITH UR;
Finished after 14 seconds elapsed
Join column not 1st in index
![Page 20: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/20.jpg)
Why?
• The 1st example is a correlated sub-query where the inner query is executed for every row of the outer query.
• The 2nd example is a join that has no suitable index.
• The 3rd example is a non-correlated sub-query where the inner query is executed only once, the result table is kept sorted in memory and the external query checks against it.
![Page 21: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/21.jpg)
Need a date ?
Select distinct current datefrom table1;
select current datefrom sysibm.sysdummy1;
EXEC SQLSET :HV = CURRENT DATE ;
![Page 22: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/22.jpg)
Sub Select – IN vs. EXISTS (3)
SELECT A, B, C FROM TAB1WHERE EXISTS
(SELECT 1 FROM TAB2 WHERE ……);
OUTER
INNER
![Page 23: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/23.jpg)
Sub Select – IN vs. EXISTS (4)
• If the “inner” table is big or if there is usable index on it then EXISTS will perform better.
• If the “inner” table is small or there is no usable index on it then IN will perform better.
• If there are few rows that qualify then the query will be converted to IN (list) which allows a matching index scan.
![Page 24: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/24.jpg)
SELECT *
• Don’t use “SELECT *” unless you really need all columns.
• Each column has to be moved from DB2 page to the DM, then to the RDS and then to the working program.
• This move is done field by field.
![Page 25: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/25.jpg)
ORDER BY
• Include only the columns needed for the sort.
Select A1, B1, C1From tableWhere A1 = :hv1Order by A1, A2, A3
Select A1, B1, C1From tableWhere A1 = :hv1Order by A2, A3
![Page 26: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/26.jpg)
Cursor within a cursor
• Cursor within a cursor (in program code) means a lot of unnecessary open & close operations of the internal cursor.
• Code it as a join / sub-select / in-list instead.
![Page 27: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/27.jpg)
Divide and conquer
• Teachers table• Courses table• Each teacher can teach any
number of courses.• We look for teachers who can
teach all courses.
![Page 28: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/28.jpg)
DIVIDE (1)
CREATE TABLE DIV1 (KD1 INT NOT NULL, DD1 CHAR(5) NOT NULL);
CREATE TABLE DIV2 (KD2 INT NOT NULL, KD1 INT NOT NULL);
Bring all records from DIV2 which have all occurrences from DIV1.
![Page 29: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/29.jpg)
DIVIDE (2)
1 AAA
2 BBB
3 CCC
100100 11
100100 22
100100 33
101101 11
101101 55
102102 11
102102 22
102102 33
102102 44
104104 11
DIV1
DIV2
Result: 100
KD1 DD1
KD2 KD1
![Page 30: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/30.jpg)
DIVIDE (3)
SELECT A.KD2 FROM (SELECT DISTINCT DIV2.KD2 AS KD2, DIV2.KD1 AS KD1 FROM DIV2 GROUP BY DIV2.KD2, DIV2.KD1) AS A
GROUP BY A.KD2 HAVING COUNT(*) = (SELECT COUNT(*) FROM DIV1) AND NOT EXISTS (SELECT DIV2.KD1 FROM DIV2 WHERE A.KD2=DIV2.KD2 AND DIV2.KD1 NOT IN (SELECT DIV1.KD1 FROM DIV1));
![Page 31: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/31.jpg)
Find Duplicates
SELECT A, B, C, COUNT(*) AS ‘NUM#’FROM T1GROUP BY A, B, CHAVING COUNT(*) > 1[ORDER BY 4 DESC]
![Page 32: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/32.jpg)
GROUP BY ON FUNCTIONS (1)
SELECT DEPT, GROSS_SALARYFROM (SELECT DEPT, SALARY+BONUS
AS GROSS_SALARY FROM EMP WHERE RANK >= 30) AS A
GROUP BY DEPT, GROSS_SALARY
![Page 33: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/33.jpg)
GROUP BY ON FUNCTIONS (2)
SELECT SUM(SALARY), MONTH_SALFROM (SELECT SALARY
,MONTH(SALARY_DATE) AS MONTH_SAL FROM EMP ) AS A
GROUP BY MONTH_SAL
![Page 34: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/34.jpg)
How much (does it costs) ?
Statement typeStatement type Estimated number of machine instructions
Simple FETCHSimple FETCH 3,500 to 9,000
Singleton SELECTSingleton SELECT 12,000 to 40,000
Update/Delete/InsertUpdate/Delete/Insert 40,000 to 90,000
![Page 35: DB2 CURSOR](https://reader033.fdocuments.in/reader033/viewer/2022061116/5464eb3cb4af9f34788b46fe/html5/thumbnails/35.jpg)
The ENDThe END