2017-05-24 1 views
0

Je cours une série de très longues déclarations, en déplaçant beaucoup de données. L'instruction en question ressemble à quelque chose comme ceci:Déclaration est 250 fois plus lent que d'habitude

CREATE TABLE a (...); 
WITH cte_1 AS (...), 
cte_2 AS (...) 
INSERT INTO a (...) 
SELECT .... 

Cela crée la table et la remplit avec environ 60 000 grandes lignes. Habituellement, cela prenait environ 1 seconde pour effectuer cette déclaration. "Habituellement" signifie que le même environnement (toutes les tables et données sont créées par un script - aucune interaction manuelle, donc toutes les instances du même environnement sont identiques quand il s'agit de données et de structure de données) mais sur une machine différente, prend juste 1 seconde pour l'exécuter.

Mais sur une nouvelle machine que j'ai, cette déclaration prend soudainement 4,5 minutes pour terminer. Pendant ce temps, Postgresql prend 100% du cœur d'un CPU. Pendant ce temps, si j'ouvre une nouvelle connexion, disons, avec DBeaver, et exécute exactement la même requête, avec un seul changement (créant la table b à la place, et insérant là, à partir des mêmes sources de données), cela prend 0.8 secondes pour terminer, pendant le temps que la première requête est en cours d'exécution.

Donc, ce n'est certainement pas le script, mais plutôt quelque chose à propos du fonctionnement interne de Postgresql, ou de sa config. C'est pourquoi je le partage, au lieu du code.

Oh, et cette requête:

SELECT 
    pid, datname, usename, 
    application_name, query, state, 
    to_char(current_timestamp - query_start, 'HH24:MI:SS') AS running_for 
FROM pg_stat_activity; 

sorties 2 procédés de DBeaver (SHOW search_path qui est inactif, et la demande de recherche ci-dessus), et la demande de recherche lente:

9736 my_db my_user psql actif 00 : 02: 42

Sur des centaines d'instructions, dans divers schémas, avec diverses complexités, c'est la seule affectée. La seule chose qui a été modifiée qui a ralenti, c'est le nouvel OS (Ubuntu 17.04), avec probablement cette nouvelle config, puisque l'ancienne a été perdue parce que mon mac est mort.

data_directory = '/var/lib/postgresql/9.6/main' 
hba_file = '/etc/postgresql/9.6/main/pg_hba.conf' 
ident_file = '/etc/postgresql/9.6/main/pg_ident.conf' 
external_pid_file = '/var/run/postgresql/9.6-main.pid' 

listen_addresses = '*' 
port = 5432 
max_connections = 40 

unix_socket_directories = '/var/run/postgresql' 

shared_buffers = 4GB 
temp_buffers = 2GB 
work_mem = 512MB 
maintenance_work_mem = 2GB 
dynamic_shared_memory_type = posix 

wal_level = minimal 
fsync = off 
synchronous_commit = off 
full_page_writes = off 
wal_buffers = 16MB 

max_wal_size = 4GB 
checkpoint_completion_target = 0.9 

seq_page_cost = 1.0 
random_page_cost = 1.5 
effective_cache_size = 12GB 

default_statistics_target = 500 

logging_collector = on 
log_directory = 'pg_log' 
log_filename = 'query.log' 
log_min_duration_statement = 0 

debug_print_parse = off 
debug_print_rewritten = off 
debug_print_plan = off 
debug_pretty_print = on 
log_checkpoints = off 
log_connections = off 
log_disconnections = off 

session_preload_libraries = 'auto_explain' 
auto_explain.log_min_duration = '2s' 

auto_explain.log_nested_statements = true 
auto_explain.log_verbose = true 

autovacuum = on 
autovacuum_max_workers = 1 

datestyle = 'iso, mdy' 
timezone = 'UTC' 


lc_messages = 'C' 
lc_monetary = 'C' 
lc_numeric = 'C' 
lc_time = 'C' 

default_text_search_config = 'pg_catalog.english' 

max_locks_per_transaction = 2048 

shared_preload_libraries = 'cstore_fdw' 

par demande, c'est une ancienne sauvegarde que j'avais, d'une autre configuration, où je me suis ajusté manuellement à seulement 1 point (shared_buffers), et le reste est à peu près par défaut.

Mise à jour SKIPPED ancienne config J'ai remplacé la config avec l'ancien, et encore eu le même problème, sauf que maintenant tout était plus lent.

mise à jour Notable la requête est devenue rapide comme l'éclair à nouveau quand j'ajouté

ANALYZE source_table1; 
ANALYZE source_table2; 
ANALYZE source_table3; 

sur les plus grandes tables qui ont été interrogés, avant d'exécuter la requête. Je n'avais pas à le faire avant et ça marchait parfaitement bien.

+0

Comme je l'ai déjà expliqué, "Slow" est relatif à la même requête, exécutée sur la même base de données EXACT, sur la même machine EXACT, juste avec un client différent. Toutes les machines, toutes les situations où cette requête s'exécute, cela prend moins d'une seconde. La seule chose différente est que cela fonctionne dans une séquence de scripts automatisés avec psql, sur un nouveau système. – AlexanderMP

+0

Comment vous exécutez la requête "lente"? n'a aucun sens travailler plus vite en utilisant un client différent. –

+0

La requête "lente" est exécutée par un script PHP, via une commande shell "psql", le long d'une myriade de requêtes beaucoup plus grandes et beaucoup plus petites, qui ne sont pas affectées par cela. – AlexanderMP

Répondre

1

Ceci est un scénario qui pourrait expliquer le comportement que vous voyez.Cela suppose que le SOURCE_TABLE {1,2,3} sont directement à la reconstruction avant que la requête est calculée (comme il se passerait-il quand il fait partie d'un ETL):

Avant:

  • tables source pour la requête sont créés
  • autovacuum a le temps de faire un ANALYZE sur la table pendant un autre processus se termine
  • postgres choisit le bon plan sur la requête

Si maintenant les données ou ETL chan ges un peu et cela se traduit par postgres n'ayant pas le temps pour autovacuum avant la requête, puis les statistiques sont désactivées et le temps d'exécution de la requête explose.