如何优化像这样需要 17 秒的查询

如何解决如何优化像这样需要 17 秒的查询

欢迎提供提示。我试图在 id_contrato 上创建一个表达式索引,但它只给了我 1 秒的速度。查询需要 17 秒。我只需要一些中到小的改进。我使用的是 Firebird 2.0。

select sum(VL_EMPENHO) as VL_EMPENHO from (select distinct
 E.ID_EMPENHO || '/' || E.ID_EXERCICIO as NUM_EMPENHO,E.DATA,E.VALOR + coalesce((select SUM(E__.VALOR) from CONTABIL_EMPENHO E__ where E__.ID_EMPENHO = E.ID_EMPENHO and E__.NUMERO = E.NUMERO
     and E__.ID_ORGAO = E.ID_ORGAO and E__.ID_EXERCICIO = E.ID_EXERCICIO
        and (E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA = 'EOA')),0) +
        coalesce((              select sum(V.VALOR)
             from CONTABIL_VARIACAO V
             LEFT JOIN CONTABIL_EVENTO ev on ev.ID_FICHA = v.ID_FICHA and ev.ID_EXERCICIO = v.ID_EXERCICIO
             LEFT JOIN CONTABIL_EVENTO_ITEM EI on EI.ID_EVENTO = ev.ID_EVENTO and EI.TIPO_EVENTO = ev.TIPO_EVENTO
             LEFT JOIN CONTABIL_PLANO_CONTA PD ON PD.ID_REGPLANO = EI.ID_DEBITO
             LEFT JOIN CONTABIL_PLANO_CONTA PC ON PC.ID_REGPLANO = EI.ID_CREDITO
             where ((PD.id_plano in ( '632910100','631990000') or  PC.id_plano in ( '632910100','631990000') )             or (PD.id_plano in ( '195920000','195910000') or  PC.id_plano in ( '195920000','195910000') ))
             AND V.ID_EMPENHO = E.ID_EMPENHO 
             and V.ANO = E.ID_EXERCICIO and V.ID_ORGAO = E.ID_ORGAO
         ),0) as VL_EMPENHO,(select first 1 P.DATA from CONTABIL_PAGAMENTO P
 inner join CONTABIL_EMPENHO E__ on E__.ID_REGEMPENHO = P.ID_REGEMPENHO
 where 
     (E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA in ('EMO','SEO','EMR','SER'))
    and E__.ID_EXERCICIO = E.ID_EXERCICIO and E__.ID_ORGAO = E.ID_ORGAO and 
    E__.ID_EMPENHO = E.ID_EMPENHO and P.ANULACAO = 'N' order by P.ID_PAGTO desc) as DT_PAGTO,(select sum(P.VALOR) from CONTABIL_PAGAMENTO P
 inner join CONTABIL_EMPENHO E__ on E__.ID_REGEMPENHO = P.ID_REGEMPENHO
 where 
     (E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA in ('EMO','SER'))
    and E__.ID_EXERCICIO = E.ID_EXERCICIO and E__.ID_ORGAO = E.ID_ORGAO and 
    E__.ID_EMPENHO = E.ID_EMPENHO) as VL_PAGO     
from CONTABIL_CONTRATO C
left join CONTABIL_EMPENHO E on substring(E.ID_CONTRATO from 1 for 8) = substring(C.ID_CONTRATO from 1 for 8) and
 E.ID_ORGAO = C.ID_ORGAO and E.TIPO_DESPESA in ('EMO')
where C.ID_ORGAO = '020000' and C.ID_CONTRATO like '00072017%' and E.ID_COMPRA <> 0 order by 1,2)

解决方法

许多可能有助于您查询的项目。对于索引,我将首先使用以下内容来帮助优化

table                index
CONTABIL_EMPENHO     ( ID_ORGAO,TIPO_DESPESA,ID_CONTRATO,ID_EMPENHO,ID_EXERCICIO )
CONTABIL_VARIACAO    ( ID_ORGAO,ANO )
CONTABIL_PAGAMENTO   ( ID_REGEMPENHO )

您最后的 WHERE 子句包含“E”别名,它将您的 LEFT JOIN 转换为 INNER JOIN,因此我只是将“AND”子句移至“E”连接部分。由于您的外部查询正在对内部表结果执行 SUM(),因此您不需要 'order by 1,2' 子句,因此我将其删除。

你加入了

    CONTABIL_CONTRATO C join CONTABIL_EMPENHO E 
            on    substring( E.ID_CONTRATO from 1 for 8) 
                = substring( C.ID_CONTRATO from 1 for 8) 

很可能会给您重复/错误的答案,因为您正在比较承包商 ID 的左侧 8 个字符。因此,让我们看一下以下示例数据。请注意,每个 ID 都以“12345678”开头,代表从 1 到 8 的子串。如您所见,这会留下 ID 的其余部分,这些 ID 将导致错误的连接结果。

CONTABIL_CONTRATO C
ID_CONTRATO
12345678A
12345678B
12345678C
12345678D


CONTABIL_EMPENHO E 
ID_CONTRATO
12345678E
12345678F
12345678G
12345678H

在没有看到实际数据的情况下,这将创建 16 倍的结果

C.ID =12345678(A) joins to E.12345678(E),E.12345678(F),E.12345678(G) and E.12345678(H)
C.ID =12345678(B) joins to E.12345678(E),E.12345678(G) and E.12345678(H)
C.ID =12345678(C) joins to E.12345678(E),E.12345678(G) and E.12345678(H)
C.ID =12345678(D) joins to E.12345678(E),E.12345678(G) and E.12345678(H)

但是你也会有同样的

(B) joined to (E) (F) (G) (H)
(C) joined to (E) (F) (G) (H)
(D) joined to (E) (F) (G) (H)

然后反过来

(E) joined to (A) (B) (C) (D)
(F) joined to (A) (B) (C) (D)
(G) joined to (A) (B) (C) (D)
(H) joined to (A) (B) (C) (D)

因此,对于每个实例,您一遍又一遍地重新查询相同的列子选择以获得相同的重复数据,我认为这完全不符合您的要求。但没有看到实际数据,无法确认。

您可能想要的是 C.contractor ID = E.contractor ID。您的 FINAL where 条款明确将范围限制为承包商,如“00072017%”,会将您的结果限制在那些有问题的承包商。因此,我将 JOIN 更改为使用相同的匹配承包商 ID。

但这会被完全消除,因为除了连接到 CONTABIL_EMPENHO 之外,您从未真正使用过 CONTABIL_CONTRATO 表。由于两个公共列都在两个表中,我只是更改了 where 子句以将“E”列引用到 ID_ORGAO 和 ID_CONTRATO 值。

对于您的每个coalesce(),由于主where 子句已经具有E.TIPO_DESPESA = 'EMO',因此在内部列选择查询中不需要它。

select 
        sum( PQ.VL_EMPENHO) VL_EMPENHO 
    from 
    (
    select distinct
            E.ID_EMPENHO || '/' || E.ID_EXERCICIO NUM_EMPENHO,E.DATA,E.VALOR 
    
            + coalesce( ( select SUM(E__.VALOR) 
                            from CONTABIL_EMPENHO E__ 
                            where 
                                    E.ID_ORGAO = E__.ID_ORGAO 
                                and E__.TIPO_DESPESA = 'EOA'
                                AND E.ID_EMPENHO = E__.ID_EMPENHO
                                and E.NUMERO = E__.NUMERO
                                and E.ID_EXERCICIO = E__.ID_EXERCICIO ),0) 

            + coalesce( ( select sum(V.VALOR)
                            from CONTABIL_VARIACAO V
                                LEFT JOIN CONTABIL_EVENTO ev 
                                    on v.ID_FICHA = ev.ID_FICHA
                                    and v.ID_EXERCICIO = ev.ID_EXERCICIO
                                    LEFT JOIN CONTABIL_EVENTO_ITEM EI 
                                        on ev.ID_EVENTO = EI.ID_EVENTO 
                                        and ev.TIPO_EVENTO = EI.TIPO_EVENTO 
                                        LEFT JOIN CONTABIL_PLANO_CONTA PD
                                            ON EI.ID_DEBITO = PD.ID_REGPLANO
                                            LEFT JOIN CONTABIL_PLANO_CONTA PC 
                                                ON EI.ID_CREDITO = PC.ID_REGPLANO
                            where 
                                    E.ID_ORGAO = V.ID_ORGAO
                                and E.ID_EMPENHO = V.ID_EMPENHO 
                                and E.ID_EXERCICIO = V.ANO 
                                AND ( 
                                        (   PD.id_plano in ( '632910100','631990000')
                                        or  PC.id_plano in ( '632910100','631990000')
                                        )
                                    or 
                                        (   PD.id_plano in ( '195920000','195910000')
                                        or  PC.id_plano in ( '195920000','195910000')
                                        )
                                    )
                            ),0) as VL_EMPENHO,( select first 1 
                    P.DATA 
                from 
                    CONTABIL_EMPENHO E__ 
                        inner join CONTABIL_PAGAMENTO P
                            on E__.ID_REGEMPENHO = P.ID_REGEMPENHO 
                            AND P.ANULACAO = 'N' 
                where
                        E.ID_ORGAO = E__.ID_ORGAO 
                    and E.ID_EMPENHO = E__.ID_EMPENHO
                    and E.ID_EXERCICIO = E__.ID_EXERCICIO 
                    and E__.TIPO_DESPESA in ('EMO','SEO','EMR','SER')
                order by 
                    P.ID_PAGTO desc ) as DT_PAGTO,( select 
                    sum(P.VALOR) 
                from 
                    CONTABIL_EMPENHO E__ 
                        inner join CONTABIL_PAGAMENTO P
                            on E__.ID_REGEMPENHO = P.ID_REGEMPENHO 
                where
                        E.ID_ORGAO = E__.ID_ORGAO
                    and E.ID_EMPENHO = E__.ID_EMPENHO 
                    and E.ID_EXERCICIO = E__.ID_EXERCICIO  
                    and E__.TIPO_DESPESA in ('EMO','SER') ) as VL_PAGO
        from 
            CONTABIL_EMPENHO E 
        where 
                E.ID_ORGAO = '020000' 
            and E.ID_CONTRATO like '00072017%'
            and E.TIPO_DESPESA in 'EMO'
            and E.ID_COMPRA <> 0  ) PQ

我相信我对您的查询需求的评估是准确的。这样一来,索引的表现就会明显更好。

,

在外部查询中,您仅使用列 VL_EMPENHO。所以我从内部查询中删除了所有其他列。现在应该执行得更快了。

select sum(VL_EMPENHO) as VL_EMPENHO from (select distinct  
    E.VALOR + coalesce((select SUM(E__.VALOR) from CONTABIL_EMPENHO E__ where E__.ID_EMPENHO = E.ID_EMPENHO and E__.NUMERO = E.NUMERO
     and E__.ID_ORGAO = E.ID_ORGAO and E__.ID_EXERCICIO = E.ID_EXERCICIO
        and (E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA = 'EOA')),0) +
        coalesce((              select sum(V.VALOR)
             from CONTABIL_VARIACAO V
             LEFT JOIN CONTABIL_EVENTO ev on ev.ID_FICHA = v.ID_FICHA and ev.ID_EXERCICIO = v.ID_EXERCICIO
             LEFT JOIN CONTABIL_EVENTO_ITEM EI on EI.ID_EVENTO = ev.ID_EVENTO and EI.TIPO_EVENTO = ev.TIPO_EVENTO
             LEFT JOIN CONTABIL_PLANO_CONTA PD ON PD.ID_REGPLANO = EI.ID_DEBITO
             LEFT JOIN CONTABIL_PLANO_CONTA PC ON PC.ID_REGPLANO = EI.ID_CREDITO
             where ((PD.id_plano in ( '632910100','631990000') or  PC.id_plano in ( '632910100','631990000') )             or (PD.id_plano in ( '195920000','195910000') or  PC.id_plano in ( '195920000','195910000') ))
             AND V.ID_EMPENHO = E.ID_EMPENHO 
             and V.ANO = E.ID_EXERCICIO and V.ID_ORGAO = E.ID_ORGAO
         ),0) as VL_EMPENHO
from CONTABIL_CONTRATO C
left join CONTABIL_EMPENHO E on substring(E.ID_CONTRATO from 1 for 8) = substring(C.ID_CONTRATO from 1 for 8) and
 E.ID_ORGAO = C.ID_ORGAO and E.TIPO_DESPESA in ('EMO')
where C.ID_ORGAO = '020000' and C.ID_CONTRATO like '00072017%' and E.ID_COMPRA <> 0 order by 1,2)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-