【问题标题】:Sql query performance is lowsql查询性能低
【发布时间】:2021-11-21 18:38:57
【问题描述】:

我想优化我的 sql 查询。当我在 investors_diversificacao 表中放入大量数据时,它会变得非常缓慢并且无法加载。但由于 investors_diversificacao 表中的数据很少,它可以加载数据。

我想要帮助优化查询响应时间。

sql查询:

SELECT investors_positivador.cod_cliente, investors_saldo_financeiro.nome_cliente, investors_base_assessores.squad, investors_base_assessores.nome_investor, investors_saldo_financeiro.saldo_d0, 
                  SUM(CASE WHEN investors_posicao_geral.vencimento <= @vencimento THEN investors_posicao_geral.financeiro ELSE 0 END) AS vencimentos_ate_data, 
                  ROUND(SUM(CASE WHEN investors_diversificacao.produto = 'Fundos' THEN investors_diversificacao.net / 6 ELSE 0 END), 2) AS fundos_ate_data, investors_guia_fundos.liquidez_total, investors_positivador.contatar_liquidity_map, 
                  investors_positivador.id, investors_posicao_geral.vencimento, investors_base_assessores.nome_assessor
FROM     investors_positivador 
    INNER JOIN investors_saldo_financeiro ON cod_cliente = investors_saldo_financeiro.cod_cliente 
    INNER JOIN investors_base_assessores ON cod_assessor = investors_base_assessores.cod_assessor 
    INNER JOIN investors_posicao_geral ON investors_positivador.cod_cliente = investors_posicao_geral.cod_cliente 
    LEFT OUTER JOIN investors_diversificacao ON investors_positivador.cod_cliente = investors_diversificacao.cod_cliente 
    LEFT OUTER JOIN investors_guia_fundos ON investors_diversificacao.cnpj = investors_guia_fundos.cnpj
WHERE (investors_base_assessores.nome_investor = @investor_nome) AND (investors_saldo_financeiro.saldo_d0 > 0) 
   OR (investors_base_assessores.nome_investor = @investor_nome) AND (investors_posicao_geral.financeiro > 0) 
   OR (investors_base_assessores.nome_investor = @investor_nome) AND (investors_diversificacao.net > 0)
GROUP BY investors_positivador.cod_cliente

【问题讨论】:

  • 您的 where 标准逻辑不明确 - 将单个子句括起来没有任何意义,我怀疑您需要对您的和/或布尔表达式进行逻辑分组。
  • 您的查询无效。因此,与其担心它的性能,不如担心它是否正确。您显然处于 MySQL 臭名昭著的作弊模式中,否则您会遇到应有的语法错误。确保SET sql_mode = 'ONLY_FULL_GROUP_BY'; 退出这种有害的作弊模式。看看你的查询。您按客户分组,但您从各种表中选择列。所有这些表是否每个客户端只有一行?我对此表示怀疑。
  • 请告诉我们所有表的唯一键是什么。例如,cod_clienteinvestors_positivador 中是唯一的吗? investors_positivadorinvestors_saldo_financeiro 两个表中的哪一个包含列 cod_assessor
  • @RiggsFolly:OR 的缩进令人困惑。它在原始请求中不存在,他们提出了不同的逻辑,然后实际上在查询中以及 OP 可能想要什么。毕竟 where 子句在 (name match and saldo &gt; 0) or (name match and finance &gt; 0) or (name match and net &gt; 0) 上,这更有意义(尽管它当然可以简化)。我认为括号可能会使这一点更清楚,但它们不是必需的。除非 OP 真的想要不同的逻辑。
  • @The Impaler:这不是真的。 AND 优先于OR,所以WJHERE 子句实际上是where iba..nome_investor = @investor_nome AND (isf..saldo_d0 &gt; 0 OR ipg..financeiro &gt; 0 OR id..net &gt; 0)。这不会将外部连接变为内部连接。不要让 RiggsFolly 的编辑使用错误的缩进s of AND` 和 OR 让您感到困惑。

标签: mysql sql query-optimization


【解决方案1】:

其中一些索引可能会有所帮助:

investors_positivador:       INDEX(cod_cliente,  contatar_liquidity_map, id)
investors_saldo_financeiro:  INDEX(cod_cliente, saldo_d0,  nome_cliente)
investors_base_assessores:   INDEX(nome_investor, cod_assessor,  squad, nome_assessor)
investors_posicao_geral:     INDEX(cod_cliente, financeiro,  vencimento)
investors_diversificacao:    INDEX(cod_cliente, net,  produto, cnpj)
investors_guia_fundos:       INDEX(cnpj,  liquidez_total)

您确定要使用 WHERE 子句吗?所有ORs 都无关紧要,Riggs 的版本简化为只是

WHERE  investors_base_assessores.nome_investor = @investor_nome
  AND  investors_diversificacao.net > 0

求和前不要四舍五入;你会得到额外的舍入错误:

ROUND(SUM(IF(investors_diversificacao.produto = 'Fundos',
             investors_diversificacao.net, 0
            )
         ) / 6     -- divide after summing and before rounding
  , 2) AS fundos_ate_data

【讨论】:

  • 您似乎也成为了 RiggsFolly 请求编辑的受害者。他们在WHERE 子句中添加了与子句的行进不匹配的令人困惑的缩进,因为AND 优先于OR,反之亦然。我现在在请求中更正了这一点。再看一遍; WHERE 子句可以简化,但 ORs 一点也不相关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 2014-12-25
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
相关资源
最近更新 更多