oracle 11g亿级复杂SQL优化一例(数量级性能提升)
Posted 太白的技术博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 11g亿级复杂SQL优化一例(数量级性能提升)相关的知识,希望对你有一定的参考价值。
自从16年之后,因为工作原因,项目中就没有再使用oracle了,最近最近支持一个项目,又要开始负责这块事情了。最近在跑性能测试,配置全部调好之后,不少sql还存在性能低下的问题,主要涉及执行计划的不合理,以及相关pga隐含参数的优化。可能因为几年不接触的原因,略微有些生疏需要review了。这里以最近优化过的某个比较典型的例子为例(这里只讲思路、因为涉及到敏感信息,不给出最终结果,16C E5620@2.40GHz/45GB内存/fio 85/15 iops 8500/1500 配置,优化前100G临时空间都爆掉,到20分钟出结果,实际上允许完全调整的话,最多5分钟就可以运行出来),这个例子比较经典,它是一个产品转换的例子,从业务逻辑上来看,它需要对两个100w(100管理人*1w支产品)记录的结果集进行黑名单(是指A产品->B产品是否允许转换,A->B不允许,不意味着B->A不允许)以外的笛卡尔积关联,,重点回顾下一些重要的operation以及如何通过hint强制,子查询独立运行时的operation和作为主查询的子查询运行时的operation不相同可能会造成性能差异巨大。首先,不要指望写一段sql,既可以在oracle下运行、也可以在mysql下运行。原始的sql语句以及执行计划如下:
INSERT INTO C3( tenantid,c_code,l_serialno,c_txtfundcode, c_chargetype,f_sharemin,f_sharemax,l_hold,c_txtothercode, c_targetchargetype,c_custtype,c_flag,d_operatedate,d_cdate,c_cyno) SELECT a.tenantid,a.c_code,l_serialno, CASE a.agencytypes WHEN \'AB\' THEN a.c_prdcode ELSE COALESCE(b.c_outprdcode,a.c_prdcode) END c_txtfundcode, c_chargetype,f_sharemin,f_sharemax,l_hold, CASE a.agencytypes WHEN \'AB\'THEN a.c_othercode ELSE COALESCE(c.c_outprdcode,a.c_othercode) END c_txtothercode, c_targetchargetype,c_custtype,c_flag,d_operatedate,20100511 d_cdate,a.c_cyno FROM (SELECT 0 l_serialno, CASE t.c_mutextype WHEN \'A\' THEN \'0\' WHEN \'B\' THEN \'1\' WHEN \'C\' THEN \'2\' ELSE t.c_mutextype END c_chargetype, CASE t.c_targetsharetype WHEN \'A\' THEN \'0\' WHEN \'B\' THEN \'1\' WHEN \'C\' THEN \'2\' ELSE t.c_targetsharetype END c_targetchargetype, ar.f_cminmutex f_sharemin,99999999999999.9 f_sharemax,0 l_hold,\'2\' c_custtype, \'1\' c_flag,\'20000101\' d_operatedate, t.* FROM (SELECT fo.tenantid, fo.c_code, fo.c_prdcode,fi.c_prdcode c_othercode, fo.c_cyno,fo.c_mutextype,fi.c_mutextype c_targetsharetype, fo.d_contractdate d_contractdate, fo.c_mutextypes c_mutextypes, fo.agencytypes, fi.d_contractdate d_othercontractdate, fi.c_mutextypes c_othersharetypes FROM (SELECT DISTINCT ss.tenantid, ss.c_code, ss.c_prdcode, ss.c_cyno,ss.c_mutextype c_mutextype, ta.c_mutextypes agencytypes, getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,\'ContractDate\', \'20991231\') d_contractdate, getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,\'ShareTypes\', \'\') c_mutextypes FROM (SELECT fi.tenantid, fi.c_code, fi.c_prdcode,c.c_cyno, s.c_mutextype, fi.c_managercode FROM FUNDINFO fi, (SELECT \'A\' c_mutextype FROM DUAL UNION ALL SELECT \'B\' c_mutextype FROM DUAL UNION ALL SELECT \'C\' c_mutextype FROM DUAL) s, QUALIFY c, EXPBATCH d WHERE fi.c_code = \'F6\' AND fi.tenantid = \'*\' AND fi.c_fundstatus NOT IN (\'6\', \'9\') AND c.c_code = \'F6\' AND c.tenantid = \'*\' AND c.c_cyno = d.c_cyno AND c.c_code = d.c_code AND c.tenantid = d.tenantid AND INSTR(fi.c_mutextypes, s.c_mutextype) > 0 AND (fi.c_fundtype<>\'1\' OR NOT EXISTS(SELECT 1 FROM TEXT_PARAMETER WHERE c_paramitem = \'ChangeLimit\' AND c_paramvalue = \'1\' AND c_prdcode = fi.c_prdcode AND c_code = \'F6\' AND tenantid = \'*\')) AND fi.c_prdcode = c.c_prdcode AND c.c_issaleflag = \'1\' ) ss, EXPBATCH ta WHERE ss.c_cyno = ta.c_cyno AND ss.c_code = ta.c_code AND ss.tenantid = ta.tenantid AND ta.c_notexpparamfiles = \'0\' ) fo, (SELECT DISTINCT ss.tenantid, ss.c_code, ss.c_prdcode, ss.c_cyno,ss.c_mutextype c_mutextype, getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,\'ContractDate\', 20991231) d_contractdate, getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,\'ShareTypes\', \'\') c_mutextypes FROM (SELECT fi.tenantid, fi.c_code, fi.c_prdcode, c.c_cyno, s.c_mutextype, fi.c_managercode FROM FUNDINFO fi, (SELECT \'A\' c_mutextype FROM DUAL UNION ALL SELECT \'B\' c_mutextype FROM DUAL UNION ALL SELECT \'C\' c_mutextype FROM DUAL) s, QUALIFY c, EXPBATCH d WHERE fi.c_code = \'F6\' AND fi.tenantid = \'*\' AND c.c_code = \'F6\' AND c.tenantid = \'*\' AND c.c_cyno = d.c_cyno AND c.c_code = d.c_code AND c.tenantid = d.tenantid AND INSTR(fi.c_mutextypes, s.c_mutextype) > 0 AND fi.c_fundstatus NOT IN (\'6\', \'9\') AND (fi.c_fundtype <> \'1\' OR NOT EXISTS (SELECT 1 FROM TEXT_PARAMETER WHERE c_paramitem = \'ChangeLimit\' AND c_paramvalue = \'1\' AND c_prdcode = fi.c_prdcode AND c_code = \'F6\' AND tenantid = \'*\')) AND fi.c_prdcode = c.c_prdcode AND c.c_issaleflag = \'1\' ) ss, EXPBATCH ta WHERE ss.c_cyno = ta.c_cyno AND ss.c_code = ta.c_code AND ss.tenantid = ta.tenantid AND ta.c_notexpparamfiles = \'0\' ) fi WHERE fo.c_prdcode <> fi.c_prdcode AND fo.c_mutextype = fi.c_mutextype AND fo.c_cyno = fi.c_cyno ) t,(SELECT c_prdcode, c_cyno, MIN(a.f_cminmutex) f_cminmutex FROM ARLIMIT a WHERE c_cyno <> \'*\' AND c_code = \'F6\' AND tenantid = \'*\' GROUP BY c_prdcode, c_cyno UNION ALL SELECT c_prdcode, b.c_cyno, MIN(f_cminmutex) f_cminmutex FROM ARLIMIT a, EXPBATCH b WHERE a.c_cyno = \'*\' AND a.c_code = \'F6\' AND a.tenantid = \'*\' AND a.c_code = b.c_code AND a.tenantid = b.tenantid AND not exists (SELECT 1 FROM ARLIMIT c WHERE b.c_cyno = c.c_cyno AND a.c_prdcode = c.c_prdcode AND a.c_code = c.c_code AND a.tenantid = c.tenantid) GROUP BY c_prdcode, b.c_cyno) ar WHERE t.d_contractdate <= 20100511 AND t.d_othercontractdate <= 20100511 AND INSTR(t.c_mutextypes, t.c_mutextype) > 0 AND INSTR(t.c_othersharetypes, t.c_targetsharetype) > 0 AND t.c_prdcode = ar.c_prdcode AND t.c_cyno = ar.c_cyno AND NOT EXISTS (SELECT 1 FROM CHANGELIMIT b WHERE t.c_prdcode = b.c_prdcode AND (t.c_mutextype = b.c_mutextype OR b.c_mutextype = \'*\') AND (t.c_cyno = b.c_cyno OR b.c_cyno = \'*\') AND (t.c_othercode = b.c_othercode OR b.c_othercode = \'*\') AND (t.c_targetsharetype = b.c_othershare OR b.c_othershare = \'*\') ) ) a LEFT JOIN FUNDCODECHANGE b ON (a.c_prdcode = b.c_prdcode AND a.c_mutextype = b.c_mutextype AND a.c_code = b.c_code AND a.tenantid = b.tenantid) LEFT JOIN FUNDCODECHANGE c ON (a.c_othercode = c.c_prdcode AND a.c_targetsharetype = c.c_mutextype AND a.c_code = c.c_code AND a.tenantid = c.tenantid)
-- 此处隐藏了谓词部分 Plan Hash Value : 4256998962 -------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | Time | -------------------------------------------------------------------------------------------------------------------------- | 0 | INSERT STATEMENT | | 1 | 129 | 2103 | 00:00:26 | | 1 | LOAD TABLE CONVENTIONAL | C3 | | | | | | 2 | NESTED LOOPS OUTER | | 1 | 129 | 2103 | 00:00:26 | | 3 | VIEW | | 1 | 95 | 2102 | 00:00:26 | | * 4 | FILTER | | | | | | | * 5 | HASH JOIN | | 1 | 8105 | 2101 | 00:00:26 | | * 6 | HASH JOIN | | 1 | 8078 | 1827 | 00:00:22 | | 7 | NESTED LOOPS OUTER | | 1 | 4060 | 914 | 00:00:11 | | 8 | VIEW | | 1 | 4026 | 913 | 00:00:11 | | 9 | SORT UNIQUE | | 1 | 72 | 913 | 00:00:11 | | * 10 | FILTER | | | | | | | 11 | NESTED LOOPS | | 1 | 72 | 912 | 00:00:11 | | 12 | NESTED LOOPS | | 1 | 72 | 912 | 00:00:11 | | 13 | NESTED LOOPS | | 1 | 58 | 911 | 00:00:11 | | 14 | NESTED LOOPS | | 1 | 49 | 910 | 00:00:11 | | 15 | NESTED LOOPS | | 1500 | 46500 | 309 | 00:00:04 | | 16 | VIEW | | 3 | 9 | 6 | 00:00:01 | | 17 | UNION-ALL | | | | | | | 18 | FAST DUAL | | 1 | | 2 | 00:00:01 | | 19 | FAST DUAL | | 1 | | 2 | 00:00:01 | | 20 | FAST DUAL | | 1 | | 2 | 00:00:01 | | * 21 | TABLE ACCESS FULL | FUNDINFO | 500 | 14000 | 101 | 00:00:02 | | * 22 | TABLE ACCESS BY INDEX ROWID | QUALIFY | 1 | 18 | 1 | 00:00:01 | | * 23 | INDEX RANGE SCAN | UIDX_QUALIFY | 1 | | 1 | 00:00:01 | | * 24 | INDEX RANGE SCAN | PK_BATCH | 1 | 9 | oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)oracle11g中SQL优化(SQL TUNING)新特性之Adaptive Cursor Sharing (ACS)