迁移Oracle到PostgreSQL一个语法报错,看看Oracle CBO Query Transformations
最近在迁移oracle到基于postgresql的国产库发现了一些兼容性问题,联想到oracle对问题SQL是多么包容,我不确认已经实现oracle语法兼容的数据库,又有多少支持了Oracle在SQL查询转换中的功能,尤其是一些不必要的查询消除. 如order by elimination、Join Elimination、Common Sub-expression Elimination、subquery elimination, 这里记录一下Oracle 10053 Trace中的优化器优化形为。
PostgreSQL
highgo=# select * from tg; name | num ------+----- a | 1 a | 1 b | 23 b | 43 c | 63 (5 rows) highgo=# select count(*) from tg order by name; ERROR: column "tg.name" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: select count(*) from tg order by name;
Oracle
SQL> @53on alter session set events '10053 trace name context forever, level 1'; alter session set "_optimizer_trace"=all; SQL> select count(*) from anbob.tg order by naME; COUNT(*) ---------- 5 SQL> @53off alter session set events '10053 trace name context off'; Session altered. SQL> @t TRACEFILE -------------------------------------------------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/enmo/enmo1/trace/enmo1_ora_1367167.trc
************** Oracle 23.1 ********************* Legend The following abbreviations are used by optimizer trace. CBQT - cost-based query transformation JPPD - join predicate push-down OJPPD - old-style (non-cost-based) JPPD FPD - filter push-down PM - predicate move-around CVM - complex view merging SPJ - select-project-join SJC - set join conversion SU - subquery unnesting OBYE - order by elimination OST - old style star transformation ST - new (cbqt) star transformation CNT - count(col) to count(*) transformation JE - Join Elimination JF - join factorization CBY - connect by SLP - select list pruning DP - distinct placement VT - vector transformation AAT - Approximate Aggregate Transformation ORE - CBQT OR-Expansion LORE - Legacy OR-Expansion qb - query block LB - leaf blocks DK - distinct keys LB/K - average number of leaf blocks per key DB/K - average number of data blocks per key CLUF - clustering factor NDV - number of distinct values Resp - response cost Card - cardinality Resc - resource cost NL - nested loops (join) SM - sort merge (join) HA - hash (join) CPUSPEED - CPU Speed IOTFRSPEED - I/O transfer speed IOSEEKTIM - I/O seek time SREADTIM - average single block read time MREADTIM - average multiblock read time MBRC - average multiblock read count MAXTHR - maximum I/O system throughput SLAVETHR - average slave I/O throughput dmeth - distribution method 1: no partitioning required 2: value partitioned 4: right is random (round-robin) 128: left is random (round-robin) 8: broadcast right and partition left 16: broadcast left and partition right 32: partition left using partitioning of right 64: partition right using partitioning of left 256: run the join in serial 0: invalid distribution method sel - selectivity ptn - partition AP - adaptive plans BJ: Bushy Join CSE: Common Sub-expression Elimination DCL: Decorrelation of lateral view GBP: Group by placement JE[V2]: Join Elimination (version 2 ?) PJE: Partial Join Evaluation PPU: (Filter) Predicate Pull-up RSW: Remove subquery SHRD: Sharding SQE: subquery elimination SVM: Simple View Merge TE: Table expansion VE: Vector Encode ZM: Zone Map
Query transformations (QT) ************************** JF: Checking validity of join factorization for query block SEL$1 (#0) JF: Bypassed: has order-by clause. ST: not valid since star transformation parameter is FALSE TE: Checking validity of table expansion for query block SEL$1 (#0) TE: Bypassed: No partitioned table in query block. ORE: Checking validity of OR Expansion for query block SEL$1 (#0) VT: Initial VT validity check for query block SEL$1 (#0) VT: Bypassed: No joining conditions. BJ: Checking validity for bushy join for query block SEL$1 (#0) invalid because Not enabled by hint/parameter BJ: Bypassed: Not enabled by hint/parameter. GPUA: Checking validity of union-all group-by pushdown for query block SEL$1 (#0) GPUA: kkqgpuaCheckValidity - initial check SEL$1 (#0) GPUA: kkqgpuaCheckValidity :******* UNPARSED QUERY IS ******* SELECT COUNT(*) "COUNT(*)" FROM "ANBOB"."TG" "TG" ORDER BY "TG"."NAME" GPUA: Failed validity - no view SEL$1 (#0) GPUA: Bypassed: invalidated. CBQT bypassed for query block SEL$1 (#0): no complex view, sub-queries or UNION (ALL) queries. CBQT: Validity checks failed for 2y5dzrgmbp5ks. CSE: Considering common sub-expression elimination in query block SEL$1 (#0) ************************* Common Subexpression elimination (CSE) ************************* CSE: CSE not performed on query block SEL$1 (#0). OBYE: Considering Order-by Elimination from view SEL$1 (#0) *************************** Order-by elimination (OBYE) *************************** OBYE: OBYE performed. CVM: Considering view merge in query block SEL$1 (#0) OJE: Begin: find best directive for query block SEL$1 (#0) OJE: End: finding best directive for query block SEL$1 (#0) CNT: Considering count(col) to count(*) on query block SEL$1 (#0) ************************* Count(col) to Count(*) (CNT) ************************* CNT: COUNT() to COUNT(*) not done. query block SEL$1 (#0) unchanged Considering Query Transformations on query block SEL$1 (#0) ************************* Common Subexpression elimination (CSE) ************************* CSE: CSE not performed on query block SEL$1 (#0). AAT: Considering Approximate Aggregate Transformation on query block SEL$1 (#0) ******************************************* Approximate Aggregate Transformation (AAT) ******************************************* AAT: no exact aggregates transformed SQE: Trying SQ elimination. SVS: Query before subsumption:******* UNPARSED QUERY IS ******* SELECT COUNT(*) "COUNT(*)" FROM "ANBOB"."TG" "TG" ORDER BY "TG"."NAME" SVS: Query after subsumption:******* UNPARSED QUERY IS ******* SELECT COUNT(*) "COUNT(*)" FROM "ANBOB"."TG" "TG" ORDER BY "TG"."NAME" SU: Considering subquery unnesting in query block SEL$1 (#0) ******************** Subquery Unnest (SU) ******************** SU: Considering bottom-up subquery unnesting SJC: Considering set-join conversion in query block SEL$1 (#0) ************************* Set-Join Conversion (SJC) ************************* SJC: not performed DCL: Checking validity of group-by elimination SEL$1 (#0) DCL: Result of group-by elimination: Invalid PM: Considering predicate move-around in query block SEL$1 (#0) ************************** Predicate Move-Around (PM) ************************** PM: PM bypassed: Outer query contains no views. PM: PM bypassed: Outer query contains no views. isReduceGrByValid: Group By Validation (Failed). isReduceGrByValid: Group By Validation (Failed). WCFPD: Considering simple filter push (pre rewrite) in query block SEL$1 (#0) WCFPD: Current where clause predicates ?? GPUA: kkqgpuadrv: CBQT invalid SEL$1 (#0) SQT: Considering Statistic-based Query Transformation from query block SEL$1 (#0) *************************** Statistic-based Query Transformation (SQT) *************************** SQT: SQT bypassed: Disabled by parameter. query block SEL$1 (#0) unchanged FPD: Considering simple filter push in query block SEL$1 (#0) ?? apadrv-start sqlid=3392828708044314200 CSE: Considering common sub-expression elimination in query block SEL$1 (#0) ************************* Common Subexpression elimination (CSE) ************************* CSE: CSE not performed on query block SEL$1 (#0). =================================== SPD: END context at statement level =================================== Final query after transformations:******* UNPARSED QUERY IS ******* SELECT COUNT(*) "COUNT(*)" FROM "ANBOB"."TG" "TG" kkoqbc: optimizing query block SEL$1 (#0)
Oracle 使用了order by 消除,并未影响SQL结果。可见oracle在优化转换中的功能是对于低质SQL有多友善,是国产数据库学习的真正方向,而不仅仅是语法兼容。
一些样例,可以查看Riyaj Shamsudeen 在2008年的一个白皮书COST BASED QUERY TRANSFORMATIONS CONCEPT AND ANALYSIS USING 10053 TRACE,没错08年。
我在做10053 trace时,又发现了oracle一个考虑周到的细节。trace文件输出未完,最后一行输出为“*** TRACE SUPPRESSED, REACHED DISK THRESHOLD 1024 MB ***”, trace被暂停了,因为发现ORACLE Home所在的文件系统使用可用空间低于1G. 这是12.1以后的功能,清理空间后可以正常输出。
Filesystem Size Used Avail Use% Mounted on devtmpfs 16G 0 16G 0% /dev tmpfs 16G 1.3G 15G 9% /dev/shm tmpfs 16G 1.6G 14G 11% /run tmpfs 16G 0 16G 0% /sys/fs/cgroup /dev/mapper/ol-root 89G 89G 263M 100% / /dev/sda1 1014M 336M 679M 34% /boot tmpfs 3.2G 12K 3.2G 1% /run/user/42 tmpfs 3.2G 0 3.2G 0% /run/user/54325 tmpfs 3.2G 0 3.2G 0% /run/user/54322 tmpfs 3.2G 0 3.2G 0% /run/user/0
“TRACE SUPPRESSED, REACHED DISK THRESHOLD xxx MB” Message Printed In Trace File (Doc ID 2999532.1)
目前这篇文章还没有评论(Rss)