在帮助用户优化应用过程中,发现用户大量使用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. ABP框架之——数据访问基础架构(下)

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的一块垫脚石,我们一起精进. EF Core集成 EF Core是微软的ORM,可以使用它与主流的数据库提供商 ...

  2. bat-进程与服务

    进程 tasklist 查看进程表 关闭进程 taskkill /PID xxx taskkill -f -im unm* taskkill -f -im ice* 服务 **net** net命令不 ...

  3. Nginx开机自启

    编写service脚本: vim /usr/lib/systemd/system/nginx.service 将以下内容复制到nginx.service文件中 ps:我的nginx目录是/usr/lo ...

  4. 多校联训 DP 专题

    [UR #20]跳蚤电话 将加边变为加点,方案数为 \((n-1)!\) 除以一个数,\(dp\) 每种方案要除的数之和即可. 点击查看代码 #include<bits/stdc++.h> ...

  5. 【RocketMQ】消息的刷盘机制

    刷盘策略 CommitLog的asyncPutMessage方法中可以看到在写入消息之后,调用了submitFlushRequest方法执行刷盘策略: public class CommitLog { ...

  6. Tapdata 肖贝贝:实时数据引擎系列(六)-从 PostgreSQL 实时数据集成看增量数据缓存层的必要性

      摘要:对于 PostgreSQL 的实时数据采集, 业界经常遇到了包括:对源库性能/存储影响较大, 采集性能受限, 时间回退重新同步不支持, 数据类型较复杂等等问题.Tapdata 在解决 Pos ...

  7. AMS1117降压电路

    AMS1117芯片为正向低压差稳压器,内部集成过热保护和限流电路,其固定输出版本电压可为1.5V.1.8V.2.5V.2.85V.3.0V.3.3V.5.0V,设计采用3.3V输出即ASM1117-3 ...

  8. 记一次requests请求乱码的问题

    太懒了,直接说原因吧: 请求返回的内容含有emoji表情 我的解决办法是替换掉emoji字符: 安装库:pip install emoji 替换:emoji.demojize(CONTENT) 注意, ...

  9. TMS320F280049 ADC 模块学习

    1. 功能概述 2. 总体框图 block diagram 3.  可配置内容灵活分配到各个模块 或 某次转换中 4.  时钟配置 ADC 模块直接分频于系统最高时钟 5.  SOC 机制 6.  如 ...

  10. Java的学习日常

    当2020年10月进入大学,我选择了计算机专业,本想着自己会摒弃高中的不良习惯,认真学习.但随着和同学们的熟悉,自己的本性也逐渐暴露出来.两年懒散表现,让现在回过头的自己都不忍直视. 虽然在学习期间, ...