บทความแรกของปี 2016 เลย (จริงๆ Plan ว่าจะเขียนนานแล้ว แต่ติดงานประจำที่ Change บ่อยมากๆ) วันนี้เลยไปเจอ Shell Script ของ AIX ตั้งนึง ที่ทำหน้าดึงข้อมูลมาใส่ใน Temp Table และส่งออกเป็น Text File ไประบบอื่นผ่าน FTP แต่ปัญหา คือ ว่ามันช้ามากกกกกกกกกกกกก รันเกือบ 20 นาทียังไม่ออกเลย
SELECT DISTINCT I1.PID, I1.VALUEDATE, I1.SECURITY_ID, I1.SECURITY_CODE, I2.EFFECTIVE_STARTDATE, I3.EFFECTIVE_ENDDATE, I1.REFERENCE_RATE_CURVE, I1.TENOR, I1.REFERENCE_RATE, I1.SPREAD, I1.FIXED_RATE, I1.TRANS_FLAG, I1.LEG_FLAG, I2.CASHFLOWID AS MINCASHFLOWID FROM INVEST.I_INV_SCHEDULE AS I1 INNER JOIN INVEST.I_INV_SCHEDULE AS I2 ON I2.VALUEDATE = I1.VALUEDATE AND I2.SECURITY_ID = I1.SECURITY_ID AND I2.SECURITY_CODE = I1.SECURITY_CODE AND I2.CASHFLOWID = (SELECT MIN(I.CASHFLOWID) FROM INVEST.I_INV_SCHEDULE AS I WHERE I.VALUEDATE = I1.VALUEDATE AND I.SECURITY_ID = I1.SECURITY_ID AND I.SECURITY_CODE = I1.SECURITY_CODE AND ( ( I.TRANS_FLAG = 'FIXED' AND I.FIXED_RATE = I1.FIXED_RATE AND I.LEG_FLAG IS NULL ) OR ( I.TRANS_FLAG = 'FIXED' AND I.FIXED_RATE = I1.FIXED_RATE AND I.LEG_FLAG = I1.LEG_FLAG ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE = I1.REFERENCE_RATE AND I.REFERENCE_RATE_CURVE IS NULL AND I.TENOR IS NULL AND I.LEG_FLAG IS NULL ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE = I1.REFERENCE_RATE AND I.REFERENCE_RATE_CURVE IS NULL AND I.TENOR IS NULL AND I.LEG_FLAG = I1.LEG_FLAG ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I.TENOR = I1.TENOR AND I.REFERENCE_RATE IS NULL AND I.LEG_FLAG IS NULL ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I.TENOR IS NULL AND I.REFERENCE_RATE IS NULL AND I.LEG_FLAG = I1.LEG_FLAG ) )) INNER JOIN INVEST.I_INV_SCHEDULE AS I3 ON I3.VALUEDATE = I1.VALUEDATE AND I3.SECURITY_ID = I1.SECURITY_ID AND I3.SECURITY_CODE = I1.SECURITY_CODE AND I3.CASHFLOWID = (SELECT MAX(I.CASHFLOWID) FROM INVEST.I_INV_SCHEDULE AS I WHERE I.VALUEDATE = I1.VALUEDATE AND I.SECURITY_ID = I1.SECURITY_ID AND I.SECURITY_CODE = I1.SECURITY_CODE AND ( ( I.TRANS_FLAG = 'FIXED' AND I.FIXED_RATE = I1.FIXED_RATE AND I.LEG_FLAG IS NULL ) OR ( I.TRANS_FLAG = 'FIXED' AND I.FIXED_RATE = I1.FIXED_RATE AND I.LEG_FLAG = I1.LEG_FLAG ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE = I1.REFERENCE_RATE AND I.REFERENCE_RATE_CURVE IS NULL AND I.TENOR IS NULL AND I.LEG_FLAG IS NULL ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE = I1.REFERENCE_RATE AND I.REFERENCE_RATE_CURVE IS NULL AND I.TENOR IS NULL AND I.LEG_FLAG = I1.LEG_FLAG ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I.TENOR = I1.TENOR AND I.REFERENCE_RATE IS NULL AND I.LEG_FLAG IS NULL ) OR ( I.TRANS_FLAG = 'FLOAT' AND I.SPREAD = I1.SPREAD AND I.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I.TENOR IS NULL AND I.REFERENCE_RATE IS NULL AND I.LEG_FLAG = I1.LEG_FLAG ) )) WHERE I1.VALUEDATE = '2015-11-29' AND ( ( I2.TRANS_FLAG = 'FIXED' AND I2.FIXED_RATE = I1.FIXED_RATE AND I2.LEG_FLAG IS NULL ) OR ( I2.TRANS_FLAG = 'FIXED' AND I2.FIXED_RATE = I1.FIXED_RATE AND I2.LEG_FLAG = I1.LEG_FLAG ) OR ( I2.TRANS_FLAG = 'FLOAT' AND I2.SPREAD = I1.SPREAD AND I2.REFERENCE_RATE = I1.REFERENCE_RATE AND I2.REFERENCE_RATE_CURVE IS NULL AND I2.TENOR IS NULL AND I2.LEG_FLAG IS NULL ) OR ( I2.TRANS_FLAG = 'FLOAT' AND I2.SPREAD = I1.SPREAD AND I2.REFERENCE_RATE = I1.REFERENCE_RATE AND I2.REFERENCE_RATE_CURVE IS NULL AND I2.TENOR IS NULL AND I2.LEG_FLAG = I1.LEG_FLAG ) OR ( I2.TRANS_FLAG = 'FLOAT' AND I2.SPREAD = I1.SPREAD AND I2.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I2.TENOR = I1.TENOR AND I2.REFERENCE_RATE IS NULL AND I2.LEG_FLAG IS NULL ) OR ( I2.TRANS_FLAG = 'FLOAT' AND I2.SPREAD = I1.SPREAD AND I2.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I2.TENOR IS NULL AND I2.REFERENCE_RATE IS NULL AND I2.LEG_FLAG = I1.LEG_FLAG ) ) AND ( ( I3.TRANS_FLAG = 'FIXED' AND I3.FIXED_RATE = I1.FIXED_RATE AND I3.LEG_FLAG IS NULL ) OR ( I3.TRANS_FLAG = 'FIXED' AND I3.FIXED_RATE = I1.FIXED_RATE AND I3.LEG_FLAG = I1.LEG_FLAG ) OR ( I3.TRANS_FLAG = 'FLOAT' AND I3.SPREAD = I1.SPREAD AND I3.REFERENCE_RATE = I1.REFERENCE_RATE AND I3.REFERENCE_RATE_CURVE IS NULL AND I3.TENOR IS NULL AND I3.LEG_FLAG IS NULL ) OR ( I3.TRANS_FLAG = 'FLOAT' AND I3.SPREAD = I1.SPREAD AND I3.REFERENCE_RATE = I1.REFERENCE_RATE AND I3.REFERENCE_RATE_CURVE IS NULL AND I3.TENOR IS NULL AND I3.LEG_FLAG = I1.LEG_FLAG ) OR ( I3.TRANS_FLAG = 'FLOAT' AND I3.SPREAD = I1.SPREAD AND I3.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I3.TENOR = I1.TENOR AND I3.REFERENCE_RATE IS NULL AND I3.LEG_FLAG IS NULL ) OR ( I3.TRANS_FLAG = 'FLOAT' AND I3.SPREAD = I1.SPREAD AND I3.REFERENCE_RATE_CURVE = I1.REFERENCE_RATE_CURVE AND I3.TENOR IS NULL AND I3.REFERENCE_RATE IS NULL AND I3.LEG_FLAG = I1.LEG_FLAG ) ) ORDER BY I1.SECURITY_CODE , MINCASHFLOWID
จาก Query ตัวอย่าง เราจะพบว่า มัน Self Join เยอะมากก ซึ่งใน DBMS ถ้าตัวเจ๋งๆ มันจะแลาดพอที่จะแปลง Query ให้ดีขึ้น หรืออย่างน้อยมี Execution Plan ช่วยตรวจสอบครับ (ราคา License ของ DB แต่ละเจ้าที่มันแพงๆ ก็เพราะ Feature เหล่านี้แหละ)
งานที่ทำอยู่ DB2 เลยลองใช้ Execution Plan บน Toad และกัน ตัว IBM Data Studio มันโคตรกินแรม 5555
Execution Plan ที่ได้ครับ พบว่ามันมีส่วนของ Table Scan เยอะมากกกกครับ จำเป็นที่จะต้องลง Table Scan ให้น้อยที่สุด โดยการเพิ่ม Index ครับ การเพิ่ม Index ที่ดี เราต้องมาดู Query ที่เราใช้กันบ่อยๆก่อนนะครับ เพราะ ถ้าเพิ่ม Index ไม่เหมาะสมมันส่งผลกับการ Insert/Update นะ และตอนนี้จากการ Scan Query คร่าวๆ ดูแล้วพวกว่ามีการ Self join เยอะครับ โดยดูจาก Field "SECURITY_ID" และ "VALUEDATE" ครับ
CREATE INDEX INVEST.IDX_I_INV_SCHEDULE1 ON INVEST.I_INV_SCHEDULE ( SECURITY_ID ASC, VALUEDATE ASC ) DISALLOW REVERSE SCANS COMPRESS NO INCLUDE NULL KEYS; COMMIT;
Execution Plan หลังจากเพิ่ม Index เร็วขึ้นเหลือ 30 วินาทีครับ และมีการดึงจาก Index แทนการใช้ Table Scan ครับ
เปรียบเทียบ Cost ก่อน และหลัง เพิ่ม Index ครับ จากของเดิมที่เป็น TBSCAN (Table Scan ที่ใช้ Cost เยอะมาก) ไปใช้ IXSCAN (Index Scan) แทนครับ
เรื่องนี้เป็น Step ต้นๆ ในการปรับแต่ง Query ให้เร็วขึ้นครับ หากนึกอะไรออก ผมจะทยอยมาเขียนบทความเพิ่มนะครับ ^___^
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.