mysql - 如何在 mysql 上优化 select sum()?

标签 mysql sql select optimization

我有这个 SQL,它运行大约需要 2.5 秒。

select SUM(valorlanca0_.VALOR_PREVISTO) as col_0_0_ 
from CF_VALOR_LANCADO_DETALHADO valorlanca0_ 
inner join CF_VALOR_LANCADO valorlanca1_ on valorlanca0_.ID_VALOR_LANCADO=valorlanca1_.ID_VALOR_LANCADO 
inner join CF_LANCAMENTO lancamento2_ on valorlanca1_.ID_LANCAMENTO=lancamento2_.ID_LANCAMENTO 
inner join CF_ADMINISTRACAO administra12_ on lancamento2_.ID_ADMINISTRACAO=administra12_.ID_ADMINISTRACAO 
inner join CF_EMPRESA empresa13_ on lancamento2_.ID_EMPRESA=empresa13_.ID_EMPRESA 
inner join CF_USUARIO usuario14_ on lancamento2_.ID_USUARIO_CRIOU=usuario14_.ID_USUARIO 
left outer join CF_FORMA_PAGAMENTO formapagam9_ on valorlanca1_.ID_FORMA_PAGAMENTO=formapagam9_.ID_FORMA_PAGAMENTO 
inner join CF_CONTA conta10_ on valorlanca1_.ID_CONTA=conta10_.ID_CONTA 
left outer join CF_FATURA fatura11_ on valorlanca1_.ID_FATURA=fatura11_.ID_FATURA 
left outer join CF_CATEGORIA categoria3_ on valorlanca0_.ID_CATEGORIA=categoria3_.ID_CATEGORIA 
left outer join CF_CENTRO_CUSTO centrocust4_ on valorlanca0_.ID_CENTRO_CUSTO=centrocust4_.ID_CENTRO_CUSTO 
left outer join CF_FAV_FONTE_PAGADORA favfontepa5_ on valorlanca0_.ID_FAV_FONTE_PAGADORA=favfontepa5_.ID_FAV_FONTE_PAGADORA 
left outer join CF_CONTA_CONTABIL contaconta6_ on valorlanca0_.ID_CONTA_CONTABIL=contaconta6_.ID_CONTA_CONTABIL 
left outer join CF_CONTATO contato7_ on valorlanca0_.ID_CONTATO=contato7_.ID_CONTATO 
left outer join CF_MARCA marca8_ on valorlanca0_.ID_MARCA=marca8_.ID_MARCA 
where administra12_.ID_ADMINISTRACAO=406 and lancamento2_.TIPO_CONTA=2 and (conta10_.ID_CONTA in (2060, 404, 405, 4291, 406, 410, 4292, 403, 4355, 402, 407)) and conta10_.TIPO<>9 and lancamento2_.TIPO_TRANSACAO=10 
and (valorlanca1_.SITUACAO in (1)) and ((valorlanca1_.DATA_PREVISTA<='2015-07-22' and valorlanca1_.SITUACAO=1 or valorlanca1_.DATA_BAIXA<='2015-07-22' and valorlanca1_.SITUACAO=3) 
and conta10_.TIPO<>2 or fatura11_.DATA_VENCIMENTO<='2015-07-22' and conta10_.TIPO=2 and valorlanca1_.SITUACAO=1 or valorlanca1_.DATA_BAIXA<='2015-07-22' and conta10_.TIPO=2 and valorlanca1_.SITUACAO=3) 
and ((empresa13_.ID_EMPRESA in (422, 3643)) and usuario14_.ID_USUARIO=574 or empresa13_.ID_EMPRESA in (422, 3643))

这是解释命令

1   SIMPLE  administra12_   const   PRIMARY PRIMARY 8   const   1   Using index
1   SIMPLE  empresa13_      range   PRIMARY PRIMARY 8       2   Using where; Using index
1   SIMPLE  lancamento2_    ref     PRIMARY,FKE50FD2D68AC234EC,FKE50FD2D6574FCEF7,FKE50FD2D628D2EAE8,IDXEMPRESA IDXEMPRESA  8   controlese.empresa13_.ID_EMPRESA    225 Using index condition; Using where
1   SIMPLE  valorlanca1_    ref     PRIMARY,FK49527EEB12DDD0DA,FK49527EEBDDD55138,IDX_VL_IDL,IDX_VL_IVL FK49527EEB12DDD0DA  8   controlese.lancamento2_.ID_LANCAMENTO   1   Using where
1   SIMPLE  conta10_        eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca1_.ID_CONTA    1   Using where
1   SIMPLE  usuario14_      eq_ref  PRIMARY PRIMARY 8   controlese.lancamento2_.ID_USUARIO_CRIOU    1   Using index
1   SIMPLE  fatura11_       eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca1_.ID_FATURA   1   Using where
1   SIMPLE  formapagam9_    eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca1_.ID_FORMA_PAGAMENTO  1   Using index
1   SIMPLE  valorlanca0_    ref     FK60A3C74EA9A01AC3,IDX_VLD_IDVL FK60A3C74EA9A01AC3  8   controlese.valorlanca1_.ID_VALOR_LANCADO    1   
1   SIMPLE  categoria3_     eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca0_.ID_CATEGORIA    1   Using index
1   SIMPLE  centrocust4_    eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca0_.ID_CENTRO_CUSTO 1   Using index
1   SIMPLE  favfontepa5_    eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca0_.ID_FAV_FONTE_PAGADORA   1   Using index
1   SIMPLE  contaconta6_    eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca0_.ID_CONTA_CONTABIL   1   Using index
1   SIMPLE  contato7_       eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca0_.ID_CONTATO  1   Using index
1   SIMPLE  marca8_         eq_ref  PRIMARY PRIMARY 8   controlese.valorlanca0_.ID_MARCA    1   Using index

最大的表是 CF_VALOR_LANCADO(855m 条记录)和 CF_VALOR_LANCADO_DETALHADO(860m 条记录)。

我可以做些什么来优化我的选择?

最佳答案

那真是一个查询:)

您可以先从 WHERE 中删除未使用的表,如下所示:

select SUM(valorlanca0_.VALOR_PREVISTO) as col_0_0_ 
from CF_VALOR_LANCADO_DETALHADO valorlanca0_ 
inner join CF_VALOR_LANCADO valorlanca1_ on valorlanca0_.ID_VALOR_LANCADO=valorlanca1_.ID_VALOR_LANCADO 
inner join CF_LANCAMENTO lancamento2_ on valorlanca1_.ID_LANCAMENTO=lancamento2_.ID_LANCAMENTO 
inner join CF_ADMINISTRACAO administra12_ on lancamento2_.ID_ADMINISTRACAO=administra12_.ID_ADMINISTRACAO 
inner join CF_EMPRESA empresa13_ on lancamento2_.ID_EMPRESA=empresa13_.ID_EMPRESA 
inner join CF_USUARIO usuario14_ on lancamento2_.ID_USUARIO_CRIOU=usuario14_.ID_USUARIO 
inner join CF_CONTA conta10_ on valorlanca1_.ID_CONTA=conta10_.ID_CONTA 
left outer join CF_FATURA fatura11_ on valorlanca1_.ID_FATURA=fatura11_.ID_FATURA 
where administra12_.ID_ADMINISTRACAO=406 
    and lancamento2_.TIPO_CONTA=2 
    and (conta10_.ID_CONTA in (2060, 404, 405, 4291, 406, 410, 4292, 403, 4355, 402, 407)) 
    and conta10_.TIPO<>9 
    and lancamento2_.TIPO_TRANSACAO=10 
    and (valorlanca1_.SITUACAO in (1)) 
    and ((valorlanca1_.DATA_PREVISTA<='2015-07-22' and valorlanca1_.SITUACAO=1 or valorlanca1_.DATA_BAIXA<='2015-07-22' and valorlanca1_.SITUACAO=3) and conta10_.TIPO<>2 
        or fatura11_.DATA_VENCIMENTO<='2015-07-22' and conta10_.TIPO=2 and valorlanca1_.SITUACAO=1 
        or valorlanca1_.DATA_BAIXA<='2015-07-22' and conta10_.TIPO=2 and valorlanca1_.SITUACAO=3
        )
    and ((empresa13_.ID_EMPRESA in (422, 3643)) and usuario14_.ID_USUARIO=574 or empresa13_.ID_EMPRESA in (422, 3643))

希望对您有所帮助:)

还有一个(SQL-Server 可能会自行完成)

and ((empresa13_.ID_EMPRESA in (422, 3643)) and usuario14_.ID_USUARIO=574 or empresa13_.ID_EMPRESA in (422, 3643))

等同于

and empresa13_.ID_EMPRESA in (422, 3643) 

您也可以尝试这种更改(95% 确定它们是等效的)- 不会有嵌套的“或”,根据我的经验,这有时有助于提高性能。

and (   
(valorlanca1_.DATA_PREVISTA<='2015-07-22' and valorlanca1_.SITUACAO=1 
    or valorlanca1_.DATA_BAIXA<='2015-07-22' and valorlanca1_.SITUACAO=3
) and conta10_.TIPO<>2 
or fatura11_.DATA_VENCIMENTO<='2015-07-22' and conta10_.TIPO=2 and valorlanca1_.SITUACAO=1 
or valorlanca1_.DATA_BAIXA<='2015-07-22' and conta10_.TIPO=2 and valorlanca1_.SITUACAO=3
)

收件人:

and (   
valorlanca1_.DATA_PREVISTA   <='2015-07-22'   and valorlanca1_.SITUACAO=1 and conta10_.TIPO<>2 
or fatura11_.DATA_VENCIMENTO <='2015-07-22'   and valorlanca1_.SITUACAO=1 and conta10_.TIPO=2 
or valorlanca1_.DATA_BAIXA   <='2015-07-22'   and valorlanca1_.SITUACAO=3
)

关于mysql - 如何在 mysql 上优化 select sum()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31590938/

相关文章:

MySQL 8 不检测选择不同查询中的功能依赖性

MySQL:嵌套选择速度问题

php - 无法让 mySQL 将数字作为新列输入

sql - MySQL 是否可以通过一次查询返回多个结果集?

mysql - 基于行的 id 的 where 子句中的条件

mysql - 在 MySQL 中查找最近的纬度经度点查询不起作用

php - 在 php 中插入值

mysql - 出现 'Duplicate entry' 错误,即使我正在使用 ON DUPLICATE KEY UPDATE

多个表上的 MySQL 共享 key

mysql - 排名排行榜 - MySQL