在帮助用户优化应用过程中,发现用户大量使用union all 导致SQL解析非常缓慢的问题。考虑到这个问题很有代表意义,我觉得很有必要对于问题进行总结。

一、用户例子

WITH company_user_temp AS (SELECT '00629999000100260000' AS company_code
FROM dual
UNION ALL
SELECT '00250033000000000000' AS company_code FROM dual
UNION ALL
SELECT '00630005000300000000' AS company_code FROM dual
UNION ALL
SELECT '00460207000000000000' AS company_code FROM dual
UNION ALL
SELECT '00420089000000000000' AS company_code FROM dual
UNION ALL
SELECT '00630008000100000000' AS company_code FROM dual
UNION ALL
SELECT '00630013001000000000' AS company_code FROM dual
UNION ALL
SELECT '00620035001900000000' AS company_code FROM dual
。。。

 

用户大量使用值的union all,导致90%的时间耗在SQL解析上。

         ->  Seq Scan on dual dual_1458  (cost=0.00..1.01 rows=1 width=0) (actual time=0.003..0.004 rows=1 loops=1)
-> Seq Scan on dual dual_1459 (cost=0.00..1.01 rows=1 width=0) (actual time=0.005..0.005 rows=1 loops=1)
-> Seq Scan on dual dual_1460 (cost=0.00..1.01 rows=1 width=0) (actual time=0.003..0.004 rows=1 loops=1)
-> Seq Scan on dual dual_1461 (cost=0.00..1.01 rows=1 width=0) (actual time=0.003..0.004 rows=1 loops=1)
Planning Time: 5081.423 ms
Execution Time: 43.726 ms
(1466 rows) Time: 5230.600 ms (00:05.231)

二、问题分析

由于SQL有大量的union all,针对union all 的每个部分,SQL 都要进行解析。 由于整个SQL涉及2000多张表 (dual),整个性能非常差。考虑以下修改方式:

with company_user_temp as (select  * from (values('00629999000100260000'), ('00250033000000000000')) as company_code )
select count(*) from company_user_temp;

  

通过这种方式,可以减少整条SQL涉及表的数量,提升SQL解析的性能。

三、验证分析

由于SQL过长,无法实际修改验证,构建以下动态SQL进行验证。

1、union 方式

test=# declare
test-# v_sql text;
test-# begin
test-# v_sql:= 'WITH company_user_temp AS (';
test-# for i in 1..2000 loop
test-# v_sql:=v_sql||'select '||i||' as company_code from dual union all ';
test-# end loop;
test-# v_sql:=substr(v_sql,0,length(v_sql) - 10) ||') select count(*) from company_user_temp';
test-# execute immediate v_sql;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 6735.076 ms (00:06.735)
test=#

2、values 方式

test=# declare
test-# v_sql text;
test-# begin
test-# v_sql := 'with company_code as (select * from (values(';
test-# for i in 1..2000 loop
test-# v_sql:=v_sql||i||'),(';
test-# end loop;
test-# v_sql:=substr(v_sql,0,length(v_sql) - 2)||') as company_code ) select count(*) from company_code';
test-# execute immediate v_sql;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 10.325 ms
test=#

  

结论:可以看到,这样修改后,SQL 性能得到了大幅提升。

不当使用 union all 导致的SQL解析时间过长的问题优化的更多相关文章

  1. (转载)处理SQL解析失败导致share pool 的争用

    通过关联x$kglcursorx$kglcursor_child_sqlid视图: 通过使用Oracle10035Event事件可以找到解析失败的SQL: 通过oraclesystemdump也可以找 ...

  2. 自己实现一个SQL解析引擎

    自己实现一个SQL解析引擎 功能:将用户输入的SQL语句序列转换为一个可运行的操作序列,并返回查询的结果集. SQL的解析引擎包含查询编译与查询优化和查询的执行,主要包含3个步骤: 查询分析: 制定逻 ...

  3. SQL解析在美团的应用

    https://tech.meituan.com/SQL_parser_used_in_mtdp.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来 ...

  4. oracle 基础知识(九)----SQL解析

    一,解析过程 二,硬解析,软解析,软软解析 01,硬解析 将SQL语句通过监听器发送到Oracle时, 会触发一个Server process生成,来对该客户进程服务.Server process得到 ...

  5. 转载:一文详解SQL解析与应用

    转载地址:http://www.elecfans.com/emb/20180618696111.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来严 ...

  6. SQL解析器详解

    1.概述 最近,有同学留言关于SQL解析器方面的问题,今天笔者就为大家分享一下SQL解析器方便的一些内容. 2.内容 2.1 SQL解析器是什么? SQL解析与优化是属于编辑器方面的知识,与C语言这类 ...

  7. Pisa-Proxy 之 SQL 解析实践

    SQL 语句解析是一个重要且复杂的技术,数据库流量相关的 SQL 审计.读写分离.分片等功能都依赖于 SQL 解析,而 Pisa-Proxy 作为 Database Mesh 理念的一个实践,对数据库 ...

  8. 如何实现一个SQL解析器

    ​作者:vivo 互联网搜索团队- Deng Jie 一.背景 随着技术的不断的发展,在大数据领域出现了越来越多的技术框架.而为了降低大数据的学习成本和难度,越来越多的大数据技术和应用开始支持SQL进 ...

  9. requests的content与text导致lxml的解析问题

    title: requests的content与text导致lxml的解析问题 date: 2015-04-29 22:49:31 categories: 经验 tags: [Python,lxml, ...

随机推荐

  1. SAP 定义客户端

    SCC4  定义客户端 点击新建条目按钮  Client(客户端) R 200 Client Name(客户端名称) O   City(城市) R   Logical system(逻辑系统) R   ...

  2. linux系统调优工具

    系统调优思路 性能优化就是找到系统处理中的瓶颈以及去除这些的过程,性能优化其实是对 OS 各子系统达到一种平衡的定义.具体步骤如下: 1. 系统的运行状况: CPU -> MEM -> D ...

  3. this关键字、static关键字、方法的调用

    1.带有static关键字的方法,不可使用this关键字.因为其调用方法为类名.方法名(建议这种方式,调用不需要对象的参与),不存在对象. 2.实例方法调用必须有对象的存在,先创建对象,通过引用.的方 ...

  4. python之多进程and多线程

    图文来自互联网 一.什么是进程和线程 (https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 进程是分配资源的最小单位,线程是系统调度的最小单位. 当应用程序运行时最 ...

  5. 不要让Microsoft edge 打开IE浏览器的设置(兼容性问题)

    1打开Microsoft edge 2 打开设置 3 搜索栏搜索IE,打开即可

  6. 使用supervisor设置应用开机自启

    安装supervisor: sudo apt install supervisor -y 创建配置文件: sudo vim /etc/supervisor/conf.d/frpc.conf frpc. ...

  7. 2022-7-13 java_1 第七组 刘昀航

    @ 目录 前言 一.一些基本的指令 二.java 1.java的三个版本 2.java特点 3.运行一个java程序 三.java的数据类型 1.java基本数据类型 2.强制转换的原理 3.八种基本 ...

  8. docker容器管理操作

    Docker容器的四种状态: 运行 已暂停 重新启动 已退出 1.容器的创建 容器创建:就是将镜像加载到容器的过程. 创建容器时如果没有指定容器名称,系统会自动创建一个名称. 新创建的容器默认处于停止 ...

  9. P2532 [AHOI2012]【一本通提高组合数学】树屋阶梯

    [AHOI2012]树屋阶梯 题目描述 输入格式 一个正整数N( 1 ≤ N ≤ 500 1\le N \le 500 1≤N≤500),表示阶梯的高度. 输出格式 一个正整数,表示搭建方法的个数.( ...

  10. Cayley 公式的另一种证明

    Cayley 公式的一些广为人知的证法: Prufer 序列 Matrix-Tree 定理 然而我都不会 233,所以下面说一个生成函数角度的证法 . 我们知道 \(n\) 个节点的有标号无根树有 \ ...