Nous voulons déplacer nos bases de données du fournisseur d'hébergement Web (PostgreSQL 9.0) vers notre serveur de réseau local (essayé à la fois PostgreSQL 10 et dernier 11) Notre machine est un serveur Windows, une machine XEON rapide avec 16 Go de RAM, juste pour la base de données.
Mais même après avoir augmenté default_statistics_targer = 4000 et analysé les statistiques, nous avons du mal à exécuter beaucoup de vues qui fonctionnaient très rapidement auparavant. Il semble que le serveur du fournisseur d'hébergement Web ait été affiné et nos plans d'exécution sont probablement étranges pour une raison quelconque.
Notre Postgres est une configuration d'installation en stock.
L'exemple de requête simplifié est ci-dessous (la plus grande table est "la table dale qui fait plusieurs millions d'enregistrements (c'est une table de liaison avec des clés étrangères)), les autres tables sont beaucoup plus petites, dixièmes de milliers d'enregistrements (le système est analysé sous vide et c'est une nouvelle installation)
EXPLAIN ANALYZE
SELECT REKLAMACNY_LIST.ID REKLAMACNY_LIST_ID
FROM REKLAMACNY_LIST
WHERE REKLAMACNY_LIST.VALIDTO IS NULL
AND
( SELECT NOT tr.typ_odstupenia::boolean
AND sr.konecny_stav::boolean
FROM dale d1
CROSS JOIN typ_reklamacie tr
CROSS JOIN dale d2
CROSS JOIN stav_reklamacie sr
WHERE TRUE
AND d1.fk7 = reklamacny_list.id
AND d2.fk7 = reklamacny_list.id
AND d1.fk1 = tr.id
AND d2.fk3 = sr.id
AND sr.validto IS NULL
AND tr.validto IS NULL
AND d1.validto IS NULL
AND d2.validto IS NULL )
ORDER BY reklamacny_list_id DESC
LIMIT 100
Expliquer l'analyse pour notre serveur de test postgres 11
"Limit (cost=0.29..18432.84 rows=100 width=4) (actual time=11804.484..331036.595 rows=91 loops=1)"
" -> Index Scan Backward using reklamacny_list_pk on reklamacny_list (cost=0.29..2578713.84 rows=13990 width=4) (actual time=11804.482..331036.524 rows=91 loops=1)"
" Index Cond: (id > 0)"
" Filter: ((validto IS NULL) AND (SubPlan 1))"
" Rows Removed by Filter: 29199"
" SubPlan 1"
" -> Hash Join (cost=5.30..87.57 rows=250 width=1) (actual time=5.246..11.824 rows=1 loops=27981)"
" Hash Cond: (d2.fk3 = sr.id)"
" -> Merge Join (cost=1.85..80.76 rows=324 width=9) (actual time=5.222..11.806 rows=6 loops=27981)"
" Merge Cond: (d1.fk1 = tr.id)"
" -> Nested Loop (cost=0.71..25556.34 rows=324 width=8) (actual time=5.211..11.794 rows=6 loops=27981)"
" -> Index Scan using dale_idx_fk1 on dale d1 (cost=0.29..25510.95 rows=18 width=4) (actual time=5.195..11.772 rows=1 loops=27981)"
" Filter: (fk7 = reklamacny_list.id)"
" Rows Removed by Filter: 28432"
" -> Materialize (cost=0.42..41.38 rows=18 width=4) (actual time=0.011..0.015 rows=6 loops=27890)"
" -> Index Scan using dale_fk7_idx on dale d2 (cost=0.42..41.29 rows=18 width=4) (actual time=0.007..0.010 rows=6 loops=27890)"
" Index Cond: (fk7 = reklamacny_list.id)"
" -> Sort (cost=1.14..1.15 rows=6 width=9) (actual time=0.009..0.009 rows=1 loops=27890)"
" Sort Key: tr.id"
" Sort Method: quicksort Memory: 25kB"
" -> Seq Scan on typ_reklamacie tr (cost=0.00..1.06 rows=6 width=9) (actual time=0.002..0.004 rows=6 loops=27890)"
" Filter: (validto IS NULL)"
" -> Hash (cost=2.74..2.74 rows=57 width=9) (actual time=0.046..0.047 rows=57 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 11kB"
" -> Seq Scan on stav_reklamacie sr (cost=0.00..2.74 rows=57 width=9) (actual time=0.012..0.030 rows=57 loops=1)"
" Filter: (validto IS NULL)"
" Rows Removed by Filter: 17"
"Planning Time: 10.174 ms"
"Execution Time: 331036.893 ms"
les exécutions prennent une éternité contre un résultat immédiat sur nos tests postgres 10.0
"Limit (cost=0.29..163635.75 rows=100 width=4) (actual time=24.199..925.691 rows=70 loops=1)"
" -> Index Scan Backward using reklamacny_list_pk on reklamacny_list (cost=0.29..21326610.37 rows=13033 width=4) (actual time=24.195..925.660 rows=70 loops=1)"
" Index Cond: (id > 0)"
" Filter: ((validto IS NULL) AND (SubPlan 1))"
" Rows Removed by Filter: 27218"
" SubPlan 1"
" -> Nested Loop (cost=4.22..781.03 rows=1293 width=1) (actual time=0.018..0.034 rows=1 loops=26066)"
" -> Hash Join (cost=3.80..377.12 rows=76 width=5) (actual time=0.005..0.005 rows=1 loops=26066)"
" Hash Cond: (d2.fk3 = sr.id)"
" -> Index Scan using dale_fk7_idx on dale d2 (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.004 rows=5 loops=26066)"
" Index Cond: (fk7 = reklamacny_list.id)"
" -> Hash (cost=2.71..2.71 rows=54 width=9) (actual time=0.049..0.049 rows=54 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 11kB"
" -> Seq Scan on stav_reklamacie sr (cost=0.00..2.71 rows=54 width=9) (actual time=0.016..0.032 rows=54 loops=1)"
" Filter: (validto IS NULL)"
" Rows Removed by Filter: 17"
" -> Materialize (cost=0.42..374.87 rows=17 width=24) (actual time=0.013..0.027 rows=1 loops=25987)"
" -> Nested Loop (cost=0.42..374.78 rows=17 width=24) (actual time=0.010..0.024 rows=1 loops=25987)"
" Join Filter: (d1.fk1 = tr.id)"
" Rows Removed by Join Filter: 32"
" -> Seq Scan on typ_reklamacie tr (cost=0.00..1.06 rows=1 width=28) (actual time=0.001..0.002 rows=6 loops=25987)"
" Filter: (validto IS NULL)"
" -> Index Scan using dale_fk7_idx on dale d1 (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.003 rows=5 loops=155922)"
" Index Cond: (fk7 = reklamacny_list.id)"
"Planning time: 8.460 ms"
"Execution time: 925.870 ms"
Ce n'est qu'un exemple. Mais presque toutes les requêtes sont simplement beaucoup plus lentes sur 11 et même les choses qui durent toujours 10, sont immédiatement renvoyées par les fournisseurs Web Postgres 9.0 (qui héberge également des centaines de bases de données différentes)
Avez-vous une idée de ce qui pourrait être la question à étudier?
L'ajustement de certains paramètres de mémoire peut-il aider? (Le serveur a 16 Go uniquement pour PostgreSQL et OS, il y aura environ 50 utilisateurs se connectant) Augmenter réellement default_statisticts_target = 10000 a beaucoup aidé, mais même alors.
Une version différente de la demande avec coalesce sinon la même
EXPLAIN ANALYZE
SELECT REKLAMACNY_LIST.ID REKLAMACNY_LIST_ID
FROM REKLAMACNY_LIST
WHERE REKLAMACNY_LIST.VALIDTO IS NULL
AND REKLAMACNY_LIST.ID > 0
AND ((
( SELECT (NOT COALESCE(tr.typ_odstupenia, 'False')::boolean)
AND COALESCE(sr.konecny_stav, 'False'):: boolean
FROM dale d1
CROSS JOIN typ_reklamacie tr
CROSS JOIN dale d2
CROSS JOIN stav_reklamacie sr
WHERE TRUE
AND d1.fk7 = reklamacny_list.id
AND d2.fk7 = reklamacny_list.id
AND d1.fk1 = tr.id
AND d2.fk3 = sr.id
AND sr.validto IS NULL
AND tr.validto IS NULL
AND d1.validto IS NULL
AND d2.validto IS NULL )))
ORDER BY reklamacny_list_id DESC
LIMIT 100
Sur Postgres 11, il passe à 10 secondes (grande différence par rapport à la version précédente de la demande sans fusion)
"Limit (cost=0.29..18432.84 rows=100 width=4) (actual time=447.853..10695.583 rows=100 loops=1)"
" -> Index Scan Backward using reklamacny_list_pk on reklamacny_list (cost=0.29..2578713.84 rows=13990 width=4) (actual time=447.851..10695.495 rows=100 loops=1)"
" Index Cond: (id > 0)"
" Filter: ((validto IS NULL) AND (SubPlan 1))"
" Rows Removed by Filter: 687"
" SubPlan 1"
" -> Hash Join (cost=5.30..87.57 rows=250 width=1) (actual time=11.436..14.102 rows=1 loops=758)"
" Hash Cond: (d2.fk3 = sr.id)"
" -> Merge Join (cost=1.85..80.76 rows=324 width=9) (actual time=11.407..14.076 rows=5 loops=758)"
" Merge Cond: (d1.fk1 = tr.id)"
" -> Nested Loop (cost=0.71..25556.34 rows=324 width=8) (actual time=11.389..14.056 rows=5 loops=758)"
" -> Index Scan using dale_idx_fk1 on dale d1 (cost=0.29..25510.95 rows=18 width=4) (actual time=11.361..14.023 rows=1 loops=758)"
" Filter: (fk7 = reklamacny_list.id)"
" Rows Removed by Filter: 28432"
" -> Materialize (cost=0.42..41.38 rows=18 width=4) (actual time=0.017..0.021 rows=5 loops=754)"
" -> Index Scan using dale_fk7_idx on dale d2 (cost=0.42..41.29 rows=18 width=4) (actual time=0.009..0.012 rows=5 loops=754)"
" Index Cond: (fk7 = reklamacny_list.id)"
" -> Sort (cost=1.14..1.15 rows=6 width=9) (actual time=0.015..0.015 rows=2 loops=754)"
" Sort Key: tr.id"
" Sort Method: quicksort Memory: 25kB"
" -> Seq Scan on typ_reklamacie tr (cost=0.00..1.06 rows=6 width=9) (actual time=0.003..0.006 rows=6 loops=754)"
" Filter: (validto IS NULL)"
" -> Hash (cost=2.74..2.74 rows=57 width=9) (actual time=0.092..0.092 rows=57 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 11kB"
" -> Seq Scan on stav_reklamacie sr (cost=0.00..2.74 rows=57 width=9) (actual time=0.032..0.068 rows=57 loops=1)"
" Filter: (validto IS NULL)"
" Rows Removed by Filter: 17"
"Planning Time: 1.556 ms"
"Execution Time: 10695.752 ms"
sur
postgres 10
"Limit (cost=0.29..163635.75 rows=100 width=4) (actual time=1.958..20.024 rows=100 loops=1)"
" -> Index Scan Backward using reklamacny_list_pk on reklamacny_list (cost=0.29..21326610.37 rows=13033 width=4) (actual time=1.957..20.011 rows=100 loops=1)"
" Index Cond: (id > 0)"
" Filter: ((validto IS NULL) AND (SubPlan 1))"
" Rows Removed by Filter: 572"
" SubPlan 1"
" -> Nested Loop (cost=4.22..781.03 rows=1293 width=1) (actual time=0.017..0.031 rows=1 loops=609)"
" -> Hash Join (cost=3.80..377.12 rows=76 width=5) (actual time=0.004..0.004 rows=1 loops=609)"
" Hash Cond: (d2.fk3 = sr.id)"
" -> Index Scan using dale_fk7_idx on dale d2 (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.003 rows=5 loops=609)"
" Index Cond: (fk7 = reklamacny_list.id)"
" -> Hash (cost=2.71..2.71 rows=54 width=9) (actual time=0.037..0.037 rows=54 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 11kB"
" -> Seq Scan on stav_reklamacie sr (cost=0.00..2.71 rows=54 width=9) (actual time=0.009..0.023 rows=54 loops=1)"
" Filter: (validto IS NULL)"
" Rows Removed by Filter: 17"
" -> Materialize (cost=0.42..374.87 rows=17 width=24) (actual time=0.013..0.025 rows=1 loops=604)"
" -> Nested Loop (cost=0.42..374.78 rows=17 width=24) (actual time=0.010..0.022 rows=1 loops=604)"
" Join Filter: (d1.fk1 = tr.id)"
" Rows Removed by Join Filter: 31"
" -> Seq Scan on typ_reklamacie tr (cost=0.00..1.06 rows=1 width=28) (actual time=0.001..0.002 rows=6 loops=604)"
" Filter: (validto IS NULL)"
" -> Index Scan using dale_fk7_idx on dale d1 (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.003 rows=5 loops=3624)"
" Index Cond: (fk7 = reklamacny_list.id)"
"Planning time: 1.418 ms"
"Execution time: 20.193 ms"
Je joins des journaux complets dans un fichier Zip (y compris la configuration postgres.conf). Il semble que l'augmentation de l'objectif statistique par défaut aide, mais uniquement avec des valeurs très élevées.
https://www.dropbox.com/s/7m3wy9nkapqitca/SpeedTest.zip?dl=
Le défaut postgresql.conf
la configuration concerne uniquement les bases de données à faible encombrement et sera lente si votre base de données est volumineuse et interrogée à l'aide de jointures complexes.
J'ai vu dans votre fichier de configuration postgresql10 que votre mémoire partagée est uniquement définie sur 128MB
(de nombreux autres paramètres sont également très petits). Vous devez reconfigurer cela.
Le réglage du serveur PostgreSQL est un sujet important et différents types de matériel nécessiteraient également des paramètres différents, ce qui s'accompagne également d'essais et d'erreurs tout en améliorant continuellement les paramètres/configuration.
Je ne suis pas en mesure de discuter de l'ensemble du topie ici, je suis juste en mesure de fournir les paramètres optimisés que j'avais l'habitude d'utiliser.
max_connections : 800
shared_buffers : 1536MB
work_mem : 24MB
maintenance_work_mem : 480MB
vacuum_cost_delay : 20ms
synchronous_commit : local
wal_buffers : 8MB
max_wal_size : 1536GB
checkpoint_completion_target : 0.9
effective_cache_size : 4GB
deadlock_timeout : 3s
log_min_duration_statement : 5000
log_error_verbosity : verbose
log_autovacuum_min_duration : 10000
log_lock_waits : on
psql 10: tampons: hit partagé = 4.439.193
psql 09: Tampons: hit partagé = ____ 7.493 lu = 686
https://www.postgresql.org/docs/11/sql-explain.html
Inclure des informations sur l'utilisation du tampon. Spécifiquement, incluez le nombre de blocs partagés frappés, lus, salis et écrits, le nombre de blocs locaux frappés, lus, salis et écrits et le nombre de blocs temporaires lus et écrits. Un hit signifie qu'une lecture a été évitée car le bloc a déjà été trouvé dans le cache en cas de besoin. Les blocs partagés contiennent des données de tables et d'index ordinaires; les blocs locaux contiennent des données provenant de tables et d'index temporaires; tandis que les blocs temporaires contiennent des données de travail à court terme utilisées dans les tris, les hachages, les nœuds de plan Materialise et les cas similaires. Le nombre de blocs salis indique le nombre de blocs non modifiés précédemment qui ont été modifiés par cette requête; tandis que le nombre de blocs écrits indique le nombre de blocs précédemment salis expulsés du cache par ce backend pendant le traitement des requêtes. Le nombre de blocs affichés pour un nœud de niveau supérieur inclut ceux utilisés par tous ses nœuds enfants. Au format texte, seules les valeurs non nulles sont imprimées. Ce paramètre ne peut être utilisé que lorsque ANALYSER est également activé. Il est par défaut FAUX.
quelque chose ne va pas avec db sur le p09 il y a ~ 8000 implications de tampon sur le p10 il y a 4M de hits de tampon
s'il s'agit du même ensemble de données, il doit y avoir beaucoup de lignes vides/supprimées dans les bases de données.
si tel est le cas, le vide devrait vous aider.
les plans d'exécuption sont assez différents, l'estimation du nombre de lignes impliquées est différente statisc mis à jour sur des colonnes spécifiques peut aider
https://www.citusdata.com/blog/2018/03/06/postgres-planner-and-its-usage-of-statistics/
psql 09 plan n'a pas de partie de tri séparée. peut-être que les index ne sont pas les mêmes. psql 09 obtient peut-être déjà la date dans le bon ordre ....