AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 335887
Accepted
Arnfred
Arnfred
Asked: 2024-02-16 02:01:22 +0800 CST2024-02-16 02:01:22 +0800 CST 2024-02-16 02:01:22 +0800 CST

Selecione consulta com mais de 90 parâmetros intermitentemente 20x mais lento na instância RDS PostgreSQL ao usar o pool de conexões

  • 772

Estou executando uma instrução select em uma tabela postgresql (em uma instância RDS) para somar valores em 2 mil linhas. A instrução select tem cerca de 100 parâmetros (principalmente países diferentes que queremos somar).

Quando executo essa consulta uma vez em meu aplicativo, ela será executada em aproximadamente 500 ms. No entanto, quando eu o executo várias vezes seguidas, a latência da consulta aumenta repentinamente de 10 a 20 vezes , para aproximadamente 5 a 10 segundos após 8 ou 9 execuções. (Essas medições são do lado do servidor dos logs RDS onde eu habilitei log_min_duration_statement).

O que poderia causar esse salto no tempo de execução? - Eu esperaria que a consulta fosse mais lenta na execução inicial, mas estou surpreso ao ver a latência aumentar após várias execuções consecutivas.

Algumas observações importantes:

  • Pool de conexões : o pool de conexões exato não parece importar. O problema persiste quer eu use HikariCP ou C3P0
  • Conexão única : esse problema não acontece se eu configurar meu pool de conexões para ter apenas uma única conexão (portanto, a lógica do aplicativo não é a culpada)
  • PSQL : Esse problema também não acontece se eu comparar a consulta consequentemente usando psqlpara executá-la.
  • Parâmetros de consulta : quando reduzo a quantidade de parâmetros de consulta para aproximadamente 60, não vejo nenhum problema. Somente quando procuro mais de 90 territórios é que me deparo com esse comportamento.
  • Redefinição do pool : quando eu reinicio meu aplicativo (e, portanto, redefino o pool de conexões), as consultas voltam a ser rápidas (0,5s) por mais 8 a 9 consultas antes de ficarem lentas novamente (5s).

Tentei procurar os suspeitos do costume, como otimização do RDS IOPS Burst, carga do banco de dados e consumo de memória, conexões disponíveis, mas nada parece suspeito nesse aspecto.

Também me certifiquei de que o índice que a consulta está usando e as linhas retornadas da tabela sejam armazenadas em cache.

A consulta que estou executando tem o seguinte formato. Trunquei alguns dos 90 IDs de países:

SELECT d.primary_title_no,
       SUM(d.cume) AS lifetime
  FROM schema.my_data AS d 
 WHERE d.currency = 'USD'
   AND d.date >= '2020-01-01'::date + (7 * (d.week - 1))
   AND d.date < '2021-01-01'::date + (7 * (d.week - 1))
   AND d.is_lifetime = TRUE
   AND d.ter_id IN ('AE','AM', ... (100 odd values) ...,'WA','ZA')
 GROUP BY d.primary_title_no 
 ORDER BY lifetime DESC
 LIMIT 250;

É importante ressaltar que esse problema só acontece quando a consulta tem mais de 90 IDs de países. Posso executá-lo em 50 países sem problemas.

Para referência, aqui está o resultado de explain analyzeuma consulta com um tempo de execução rápido:

+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| QUERY PLAN                                                                                                                                                                                                                                                                                                                                                                             |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Limit  (cost=1218692.98..1218693.23 rows=100 width=12) (actual time=369.146..369.167 rows=100 loops=1)                                                                                                                                                                                                                                                                                 |
|   ->  Sort  (cost=1218692.98..1218697.34 rows=1742 width=12) (actual time=369.145..369.154 rows=100 loops=1)                                                                                                                                                                                                                                                                           |
|         Sort Key: (sum(cume)) DESC                                                                                                                                                                                                                                                                                                                                                     |
|         Sort Method: top-N heapsort  Memory: 33kB                                                                                                                                                                                                                                                                                                                                      |
|         ->  GroupAggregate  (cost=1218595.34..1218626.41 rows=1742 width=12) (actual time=366.250..368.653 rows=1959 loops=1)                                                                                                                                                                                                                                                          |
|               Group Key: primary_title_no                                                                                                                                                                                                                                                                                                                                              |
|               ->  Sort  (cost=1218595.34..1218599.89 rows=1820 width=12) (actual time=366.240..366.844 rows=5739 loops=1)                                                                                                                                                                                                                                                              |
|                     Sort Key: primary_title_no                                                                                                                                                                                                                                                                                                                                         |
|                     Sort Method: quicksort  Memory: 462kB                                                                                                                                                                                                                                                                                                                              |
|                     ->  Index Scan using idx_dailies_currency_ter_id_primary_title_no_lifetime on dailies d  (cost=0.43..1218496.79 rows=1820 width=12) (actual time=1.093..364.406 rows=5739 loops=1)                                                                                                                                                                                 |
|                           Index Cond: (((currency)::text = 'USD'::text) AND ((ter_id)::text = ANY ('{AE,AM,AR,AT,AU,AZ,BA,BE,BG,BH,BO,BR,BY,CH,CL,CN,CO,CR,CU,CZ,DE,DK,DO,EC,EE,EG,ES,FI,FR,GE,GR,GT,HK,HN,HR,HU,IL,IN,IQ,IS,IT,JP,KG,KR,KW,KZ,LB,LT,LU,LV,MD,MX,MY,MZ,NI,NL,NO,NZ,OM,PA,PE,PH,PL,PT,PY,QA,RO,RS,RU,SA,SE,SG,SI,SK,SV,TH,TJ,TM,TR,TT,TW,UK,UP,UY,UZ,WA,ZA}'::text[]))) |
|                           Filter: (((date - (7 * (week - 1))) >= '2020-01-01'::date) AND ((date - (7 * (week - 1))) < '2020-06-01'::date))                                                                                                                                                                                                                                             |
|                           Rows Removed by Filter: 314494                                                                                                                                                                                                                                                                                                                               |
| Planning Time: 0.613 ms                                                                                                                                                                                                                                                                                                                                                                |
| Execution Time: 369.213 ms                                                                                                                                                                                                                                                                                                                                                             |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Para um caso em que a consulta é executada lentamente, a explain analyzesaída é a mesma, mas 20 vezes o cálculo é gasto na Index Scanetapa mais interna.

Se alguém tiver alguma indicação de como posso solucionar esse problema, serei todo ouvidos.

postgresql
  • 1 1 respostas
  • 35 Views

1 respostas

  • Voted
  1. Best Answer
    Arnfred
    2024-02-16T03:22:46+08:002024-02-16T03:22:46+08:00

    Depois de analisar mais o problema com os parâmetros, encontrei a seguinte pergunta sobre stackoverflow sugerindo que:

    Depois de executar a consulta algumas vezes, ele decide que o plano genérico é tão bom quanto o plano personalizado, então muda para o plano genérico. Aparentemente, está errado nisso. Você pode forçá-lo a usar o plano personalizado sempre definindo plan_cache_mode.

    Na documentação do Postgresql, plan_cache_mode está documentado da seguinte forma:

    Instruções preparadas (preparadas explicitamente ou geradas implicitamente, por exemplo, por PL/pgSQL) podem ser executadas usando planos personalizados ou genéricos. Os planos personalizados são feitos novamente para cada execução usando seu conjunto específico de valores de parâmetros, enquanto os planos genéricos não dependem dos valores dos parâmetros e podem ser reutilizados em execuções. Assim, o uso de um plano genérico economiza tempo de planejamento, mas se o plano ideal depende fortemente dos valores dos parâmetros, então um plano genérico pode ser ineficiente. A escolha entre essas opções normalmente é feita automaticamente, mas pode ser substituída por plan_cache_mode. Os valores permitidos são auto (o padrão), force_custom_plan e force_generic_plan. Essa configuração é considerada quando um plano em cache deve ser executado, e não quando ele é preparado. Para obter mais informações, consulte PREPARAR.

    Quando executei a seguinte instrução dentro de uma transação com minha instrução select, o problema foi resolvido:

    (jdbc/with-db-transaction [connection (db/shared-db-ro)]
      (jdbc/execute! connection ["SET LOCAL plan_cache_mode = 'force_custom_plan'"])
      (execute-slow-query params {:connection connection}))))
    

    Atualização : acho que o problema ocorre em conjunto com a work_memconfiguração de 4mb. Minha hipótese é que o plano genérico ocupa um pouco mais de memória, causando muitas trocas. Aumentar esse limite para 16 MB também resolve o problema:

    (jdbc/with-db-transaction [connection (db/shared-db-ro)]
      (jdbc/execute! connection ["SET LOCAL work_mem = '16mb'"])
      (execute-slow-query params {:connection connection}))))
    
    • 0

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve