PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#51 Re : Général » Table volumineuse » 18/06/2022 14:38:21

TRUNCATE est censé être assez rapide. Si c'est lent, il peut soit être en attente de verrous si d'autres transactions utilisent la table (c'est la première chose à vérifier), soit en attente des écritures disque.
Dans une autre session il faudrait regarder via pg_stat_activity l'état de la session qui fait le truncate, notamment les colonnes wait_event et wait_event_type.
Pour les verrous on peut aussi utiliser les requêtes suggérées ici: https://wiki.postgresql.org/wiki/Lock_Monitoring

#52 Re : Général » Problème sur requete UPDATE avec select for update » 17/05/2022 12:00:15

Une recherche dans les mailing-lists trouve une réponse de Thomas Munro sur un cas comparable:

https://www.postgresql.org/message-id/f … utlook.com

Lorsque la table dont il faut verrouiller les lignes est référencée une deuxième fois dans la requête pour jointure, il dit que les deux côtés de la jointure n'ont pas le même niveau de visibilité, ce qui produit des résultats incohérents par rapport aux attentes.

Est-ce qu'il y a une solution avec la forme actuelle de la requête? Il dit:

You'd need to make sure that the row locking applies to the same relation(s) as the WHERE clause to avoid that.

et effectivement avec la requête mentionnée en #1

UPDATE message SET is_dequeued = true
WHERE id IN (SELECT f2.id FROM message f2 WHERE f2.id_queue = 5 AND f2.is_dequeued = false ORDER BY f2.id ASC FOR UPDATE SKIP LOCKED  LIMIT 1)
returning *

on n'est pas dans la bonne situation parce que le WHERE id... s'applique à la table message au niveau supérieur alors que le FOR UPDATE s'applique à la table message aliasée en "f2" dans la sous-requête.


Pour éviter le problème, on peut j'imagine soit couper la requête en deux comme suggère Guillaume en #13, soit utiliser un niveau d'isolation supérieur, REPEATABLE READ ou SERIALIZED. Dans ces niveaux d'isolation, ce genre d'anomalie liés aux accès concurrents devrait être remonté en erreur à l'utilisateur avec annulation de la transaction, au lieu de passer en force en mode "advienne que pourra" (en READ COMMITTED).

#53 Re : PL/pgSQL » syntaxe après le FROM pour une "table variable" » 05/05/2022 12:48:37

Au-delà de l'erreur de la boucle infinie, conceptuellement le fait de créer N tables qui ont une structure identique est anti-relationnel.
Même si ça vous parait plus simple de raisonner sur des tables séparées, en BDD relationnelle on fera une seule table avec une colonne supplémentaire contenant le numéro derrière le "bp" des noms de tables actuels.

Accessoirement, en faisant comme ça, il n'y a plus besoin de SQL dynamique.


Indépendamment de ça, la boucle dans le code en #7 supprime et créé une table temporaire "temp", toujours la même. Il faudrait à la place créer la table une seule fois en dehors de la boucle, et faire un TRUNCATE dans la boucle si on veut la vider de son contenu à chaque itération.

#54 Re : Installation » Installation de PostgreSQL sous MacOSX Error: invalid version 'initdb' » 02/05/2022 20:17:11

Je n'ai jamais essayé pg_createcluster sur Mac OS (qui est un projet perso de Peter Eisentraut si je comprends bien) , mais si c'est pareil que celui utilisé par les packages Debian, cette ligne de commande a un problème:

pg_createcluster -p 5442 -l "$dbpath_parentdir/$instance_name" -u $username -e UTF-8 --locale=fr_BE -d $dbpath -- initdb -A -X $dbpath_parentdir/wals

Le souci est que derrière le -- il ne doit pas y avoir le mot initdb. Dans la doc il est dit "initdb options", mais c'est à interpréter comme "les options destinées à initdb", et non pas comme "le mot initdb suivi d'une liste d'options".

Ce qui n'empêche pas que la valeur du $dbpath n'est peut-être pas bonne par ailleurs, comme Sébastien le suggère.

#55 Re : Général » Maintenance ANALYZE sur une table entraine un out of memory » 27/04/2022 16:52:12

Quand ce type d'erreur arrive, il y a normalement du détail dans les logs qui indique combien de mémoire est allouée et comment elle est répartie. Il faudrait voir ce détail et savoir de combien de mémoire libre le serveur dispose quand l'ANALYZE est lancé.

#56 Re : Site PostgreSQL.fr » fonction et trigger concatenation » 22/04/2022 10:01:42

Dans la fonction il faut se référer au champ insee par new.insee et non insee tout seul, de même pour les autres champs de la table.

#57 Re : C et C++ » Différences entre PQexec de libpq et l'outil cmd psql.exe ? » 21/04/2022 22:23:46

psql utilise PQexec pour lancer les commandes, mais il analyse le script de commandes pour trouver le début et la fin de chaque requête et les envoie une par une après découpage.

J'ai l'impression que c'est l'étape que vous n'avez pas dans votre programme.

Ce découpage est fait dans psql avec un analyseur lexical dédié fait avec lex, qui lui même est une copie de l'analyseur lexical du moteur SQL. Voir https://git.postgresql.org/gitweb/?p=po … psqlscan.l

 * This code is mainly concerned with determining where the end of a SQL
 * statement is: we are looking for semicolons that are not within quotes,
 * comments, or parentheses.  The most reliable way to handle this is to
 * borrow the backend's flex lexer rules, lock, stock, and barrel.  The rules
 * below are (except for a few) the same as the backend's, but their actions
 * are just ECHO whereas the backend's actions generally do other things.

On peut toujours envoyer un énorme bloc plein de requêtes SQL accolées à PQexec en espérant que ça va passer, mais à titre d'exemple si on envoie ça à PQexec:

CREATE DATABASE dbtest; select 1;

ça échouera avec une erreur disant que CREATE DATABASE ne marche pas dans une transaction, alors qu'avec psql ça passerait sans erreur, parce qu'il aura découpé ça en 2 requêtes à envoyer séparément.

#58 Re : Optimisation » Materialize 25 milliards lignes » 06/04/2022 11:17:04

J'ai aussi du parallelisme sur le merge que je n'ai pas en 9.5 (la doc sur parallel plans ne me donne pas de lien 9.5) et je n'ai jamais travaillé sur cette version, est-ce que ça signifie qu'elle ne fait pas de parallelism ou de façon très limitée ?

Oui, le parallélisme intra-requête est apparu avec la version 9.6.
https://www.postgresql.org/docs/9.6/parallel-query.html


Sinon la version 11 date de 2018 et sera obsolète en 2023, il serait préférable de migrer sur la dernière version qui est la 14.

#59 Re : PL/pgSQL » Update avec requête récursive » 02/04/2022 19:18:46

La question principale est comment mettre à jour "arrival_date" et "departure_date" pour les étapes de la table steps pour une course donnée, quand on a une nouvelle date de course.

"arrival_date" pour chaque étape est égal à "departure_date" de l'étape précédente, sauf s'il n'y a pas d'étape précédente (position=0), auquel cas c'est la date de départ de la course.

"departure_date" est toujours égal à "arrival_date" + "number_of_days".

Il se trouve que les fonctions de fenêtrage permettent de faire un calcul dans une ligne en fonction des autres lignes, suivantes et/ou précédentes.
Je disais en #3 qu'on peut utiliser LAG ou une somme partielle. Je pense que le plus simple dans cette requête est d'utiliser la somme partielle des "number_of_days", avec la formule

arrival_date = date de départ course + sum(number_of_days "précédents") over (order by position)

Donc pour sortir les nouvelles dates de chaque étape, ça peut marcher avec une requête de cette forme:

SELECT
  position,
  CASE WHEN position=0 THEN
    #{date de départ de la course}
  ELSE
    #{date de départ de la course} + (interval '1 day' * sum(number_of_days)
      over (ORDER BY position ROWS between UNBOUNDED PRECEDING and 1 PRECEDING))
  END as new_arrival_date
  FROM steps
WHERE
  course_id = #{ID de la course}

Ensuite pour faire l'UPDATE on utilise simplement les résultats de cette requête avec position et course_id pour faire la jointure.

Syntaxiquement, ça donnerait une requête du style

WITH new_steps AS (
SELECT
  position,
  CASE WHEN position=0 THEN
    #{date de départ de la course}
  ELSE
    #{date de départ de la course} + (interval '1 day' * sum(number_of_days)
      over (ORDER BY position ROWS between UNBOUNDED PRECEDING and 1 PRECEDING))
  END as new_arrival_date
  FROM steps
WHERE
  course_id = #{ID de la course}
)
UPDATE steps
SET
 arrival_date = s.new_arrival_date,
 departure_date = s.new_arrival_date + number_of_days
FROM new_steps
WHERE new_steps.position = steps.position
AND course_id =  #{ID de la course}
;

#60 Re : PL/pgSQL » Update avec requête récursive » 31/03/2022 20:46:40

Il y a bien une clause where dans le with ce qui limite l'upadte... non ?

Non la simple présence du WITH ne contraint pas les lignes touchées par l'UPDATE. Si la sous-requête du WITH était utilisée pour corréler dans l'UPDATE alors OK, mais là ce n'est pas le cas (d'ailleurs dans aucune des requêtes du message #4 me semble-t-il).

Regardez dans votre client SQL combien de lignes sont affectées. Normalement cette info est affichée quelque part. Avec psql, ça affiche UPDATE N où N est le nombre de lignes, et de plus ça arrive dans la variable ROW_COUNT.

Au pire, ajoutez RETURNING * à la fin de la requête UPDATE et vous verrez aussi que ça affecte toute la table, par opposition à seulement les lignes correspondant au course_id en paramètre.

#61 Re : PL/pgSQL » Update avec requête récursive » 31/03/2022 09:49:42

Ca semble un cas typique où il faudrait utiliser la fonction de fenêtrage LAG pour récupérer dans la ligne N des valeurs de colonne de la ligne N-1, plutôt que des sous-requêtes. Il est aussi possible de cumuler des valeurs avec SUM sur chaque ligne, par exemple ici la colonne number_of_days.
Voir https://docs.postgresql.fr/14/functions-window.html

L'UPDATE tel que montré semble compter sur le fait que les lignes se mettent à jour dans un certain ordre (la mise à jour de la ligne N a besoin que la ligne N-1 ait été mise à jour avant), ce qui n'est pas vraiment possible.
Par ailleurs, il n'a pas de clause WHERE, donc il met à jour toute la table steps, ce qui semble anormal.


Il serait plus simple de décomposer le problème en écrivant déjà un SELECT qui sort les nouvelles valeurs sans rien mettre à jour. Ensuite la mise à jour peut s'écrire avec un seul UPDATE avec jointure avec les résultats de ce SELECT en sous-requête (UPDATE ... FROM (sous-requête) WHERE...)

#62 Re : Général » [Résolu] Problème avec le service Postgresql sur Debian 11 » 28/03/2022 22:33:24

Et si j'enlève 127.0.0.1 dans la conf et que je laisse uniquement l'IP locale de mon serveur à savoir 192.168.1.2 ?

Ca enlève celle qui répond et ça garde celle qui ne répond pas (enfin pas tout de suite) donc effectivement ça ne peut pas marcher.

Encore une fois, si le serveur est protégé de l'extérieur,  listen_addresses=* serait OK.


Concernant systemd, je viens d'essayer et comme prévu c'est moins simple. Effectivement  faire le changement dans postgresql.service ne semble pas marcher pour moi non plus.

Sur Debian/Ubuntu l'unité systemd postgresql est en fait un lanceur et pas le service lui-même.
La vraie unité est générée pour chaque instance suivant le modèle dans /lib/systemd/postgresql@.service

Si dans la section [Unit] de ce fichier j'ajoute

After=network-online.target

ça semble marcher pour moi avec une interface DHCP.  Ceci sur un portable Ubuntu 18.04 qui a les mêmes packages Postgres que Debian à peu de choses près, donc que je pense que ce serait pareil sur Debian. A confirmer.

#63 Re : Général » [Résolu] Problème avec le service Postgresql sur Debian 11 » 28/03/2022 21:40:32

Cette erreur ressemble effectivement à ce que je supposais en #2:

2022-03-28 19:13:11.816 CEST [792] LOG:  n'a pas pu lier IPv4 à l'adresse « 192.168.1.2 » : Ne peut attribuer l'adresse demandée
    2022-03-28 19:13:11.816 CEST [792] ASTUCE :  Un autre postmaster fonctionne-t'il déjà sur le port 5432 ?
            Sinon, attendez quelques secondes et réessayez.
    2022-03-28 19:13:11.817 CEST [792] ATTENTION:  n'a pas pu créer le socket d'écoute pour « 192.168.1.2 »

dans le postgresql.conf, il doit y avoir une déclaration du style:

  listen_addresses = 127.0.0.1,192.168.1.2

Ca dit à postgres d'écouter sur ces deux interfaces réseau. Le problème est que si 127.0.0.1 est bien accessible dès que postgres démarre au boot, 192.168.1.2 ne l'est pas.


Ca devrait pouvoir être corrigé, soit
1) de la manière la plus simple en mettant

listen_addresses = * 

à la place. Le problème est que s'il y a d'autres interfaces réseau sur la machine, notamment ouvertes sur Internet, pour la sécurité c'est mauvais. Le reste du monde peut joindre votre instance postgres au lieu que ce soit limité à votre réseau local.


2) d'une manière plus compliquée mais plus sûre en forçant postgres à attendre que les interfaces soient prêtes via systemd, sans changer listen_addresses.  Il y a une réponse ici qui va dans ce sens:
https://stackoverflow.com/questions/622 … ot-systemd

#64 Re : Général » [Résolu] Problème avec le service Postgresql sur Debian 11 » 28/03/2022 18:52:54

Le plus probable est que l'adresse réseau ne soit pas encore montée quand postgres démarre dans le contexte d'un boot, et donc il n'écoute pas dessus. Il faudrait regarder le log serveur (/var/log/postgresql/postgresql-13-main.log juste après un boot, si c'est ça il y aura des messages d'erreur à ce sujet.

#65 Re : Site PostgreSQL.fr » ERROR: invalid input syntax for type numeric: " " » 24/03/2022 12:40:33

Cette erreur arrive quand une chaîne de caractères ne peut pas être convertie dans le type numeric.
Si on regarde dans la requête ce qui convertit de texte vers numérique, cette expression semble à suspecter en premier:

to_number("substring"("substring"(groupe_session.code::text, '_(.*)'::text), '(.*?)_'::text), '9999'::text) AS annee_entree,

Ici il suffirait qu'une seule valeur de groupe_session.code ne corresponde pas au modèle attendu pour que ça échoue avec l'erreur en question.

#66 Re : Général » Ligne manquante? » 22/03/2022 21:24:30

Vous avez sans doute fait une erreur de manip. C'est facile à tester, créer une table vide avec juste les 2 colonnes requêtées

CREATE TABLE film(film_id int, length int);

Lancer la  requête copié-collée. Effectivement elle sort l'erreur mentionnée.

select case
        when length between 0 and 59 then 'Less then 1 hour'
        when length between 60 and 119 then '1 to 2 hours'
        when length between 120 and 179 then '2 to 3 hours'
        else 'over 3 hours'
        end as FilmLengthCategory
    , count (film_id) as CountofFilms
from film
group by case
        when length between 0 and 59 then 'Less then 1 hour'
        when length between 60 and 119 then '1 to 2 hours'
        when length between 120 and 179 then '2 to 3 hours'
        else 'Over 3 hours'
        end
order by CountOfFilms desc

ERREUR:  la colonne « film.length » doit apparaître dans la clause GROUP BY ou doit être utilisé dans une fonction d'agrégat
LIGNE 2 :         when length between 0 and 59 then 'Less then 1 hour'

Changer le 'over' en 'Over', relancer, résultat: plus d'erreur:

select case
        when length between 0 and 59 then 'Less then 1 hour'
        when length between 60 and 119 then '1 to 2 hours'
        when length between 120 and 179 then '2 to 3 hours'
        else 'Over 3 hours'
        end as FilmLengthCategory
    , count (film_id) as CountofFilms
from film
group by case
        when length between 0 and 59 then 'Less then 1 hour'
        when length between 60 and 119 then '1 to 2 hours'
        when length between 120 and 179 then '2 to 3 hours'
        else 'Over 3 hours'
        end
order by CountOfFilms desc

filmlengthcategory | countoffilms 
--------------------+--------------
(0 ligne)

PS: on peut aussi écrire GROUP BY 1 avec PostgreSQL pour grouper par la première colonne sans répéter toute l'expression mais c'est non-standard.

#67 Re : Installation » Hard links pas adaptés après upgrade v11 -> v13 avec pg_upgrade » 08/03/2022 11:58:50

dangil a écrit :

Merci pour vos réponses.

Si je lance le script "delete_old_cluster.sh" qui effectue simplement un "rm -rf '/opt/postgres/bsi/11'" la db aura des problèmes car certains fichiers de l'ancien répertoire V11 sont toujours touchés.
Par exemple :

-rw-------. 2 postgres postgres   17358848 Mar  8 09:15 21823741
-rw-------. 2 postgres postgres  706199552 Mar  8 09:15 17401164

Si la v13 écrit dans ces fichiers il est normal que la date de dernière modification change en regardant dans le répertoire de la v11.
Ces fichiers pointant sur le même inode, ils ont les mêmes données et aussi les mêmes métadonnées à part le nom.

Cf https://en.wikipedia.org/wiki/Inode#POS … escription

#68 Re : PL/pgSQL » Remplissage automatique » 24/02/2022 23:02:48

Ca n'a pas forcément à voir avec "bloque" mais dans le code 4) il y a une erreur classique de débutant:

WHEN "SampleType" = 'Quarter core' AND "DupSampleID"= NULL

Cette condition sera toujours fausse. Il faudrait utiliser "DupSampleID" IS NULL au lieu de "DupSampleID"=NULL.

#69 Re : PL/pgSQL » Trigger non fonctionnel Postgresql 13 » 18/02/2022 13:50:47

Pour 2) je ne sais pas ce que c'est

Pour 1) la syntaxe standard serait :

BEGIN
 NEW."Xto" := CASE WHEN "Azimuth" >=0 AND "Azimuth"<180
                THEN NEW."Xplanned"+NEW."FinalDepth"
            ELSE
                NEW."Xplanned"-NEW."FinalDepth"
            END;

NEW."Yto" := CASE WHEN "Azimuth" >=0 AND "Azimuth"<90 OR "Azimuth" >=270 AND "Azimuth"<359
                THEN NEW."Xplanned"+NEW."FinalDepth"
            ELSE 
                NEW."Xplanned"-NEW."FinalDepth"
            END;

 RETURN NEW;
END

En Postgres moderne (depuis la version 12) plutôt qu'un trigger on conseillerait plutôt de déclarer des colonnes générées, par exemple:

ALTER TABLE "DHCollar_Planned" ADD "YTo" numeric generated always
   as (CASE WHEN "Azimuth" >=0 AND "Azimuth"<90 OR "Azimuth" >=270 AND "Azimuth"<359
                THEN "Xplanned"+"FinalDepth"
            ELSE                            
                "Xplanned"-"FinalDepth"
            END) 
   stored;

#70 Re : PL/pgSQL » Trigger non fonctionnel Postgresql 13 » 17/02/2022 20:32:08

L'erreur est normale parce que l'expression CASE est  un mix incorrect des deux formes possibles de CASE

UPDATE "DHCollar_Planned"
        SET "Xto"=
            CASE New."HoleID"
            WHEN "Azimuth" >=0 AND "Azimuth"<180
                THEN New."Xplanned"+New."FinalDepth"
            ELSE
                New."Xplanned"-New."FinalDepth"
            END;

Si on veut exprimer que si "Azimuth" >=0 AND "Azimuth"<180 alors "Xto" doit prendre la valeur New."Xplanned"+New."FinalDepth" et sinon la valeur New."Xplanned"-New."FinalDepth", alors c'est la forme CASE WHEN condition1 THEN valeur1 WHEN condition2 THEN valeur2 etc... et le New."HoleID" n'a rien à faire là.

L'autre forme possible est CASE expression WHEN valeur1 THEN autre valeur ELSE ... END qui teste les égalités entre l'expression et les valeurs successives.


Un autre problème est que dans un trigger on ne met pas à jour les champs avec un nouvel UPDATE de la table qui est train d'être modifiée mais avec une assignation directe des champs: NEW.colonne := valeur;

Apparemment les champs à mettre à jour sont NEW."Xto" et NEW."Yto", mais la présence de New."HoleID" et New."YHoleID" dans ce code n'a pas de raison apparente.


Si vous avez besoin de plus d'aide sur ce code, essayez de décrire ce qu'il doit faire.

#71 Re : Migration » migration mineure PG 10.1 vers 10.20 » 17/02/2022 15:45:34

faut-il appliquer toutes les recommandations des différentes releases notes de 10.2 à 10.20 ?

Oui. Sauf cas exceptionnel précisé dans les notes, une mise à jour mineure remplace juste les exécutables, et ne fait aucune autre action en dehors de ça sur aucune des bases. Donc toutes les actions préconisées à faire manuellement restent à faire dans le cas où on saute des m.a.j. intermédiaires.

#72 Re : Optimisation » partitionning planner bloqué sur un vacuum full d'une partition ? » 17/02/2022 10:40:51

En ce qui concerne "casser le lien d'héritage".
Il faut savoir qu'avec l'héritage, sortir une table de la hiérarchie et la remettre n'est pas une opération neutre.
Une fois que la table fille est remise dans la hiérarchie, les modifications de colonnes existantes du parent ne sont plus propagées dans la table fille comme avant.
Plusieurs utilisateurs comme moi ont signalé ça comme un bug tant c'est surprenant, mais il s'avère que ce n'est pas un bug, c'est conçu comme ça.

Exemple:

DROP TABLE  IF EXISTS parent_tbl CASCADE; 

CREATE TABLE parent_tbl(f1 int, f2 int, f3 int); 

CREATE TABLE child1_tbl() INHERITS(parent_tbl); 
CREATE TABLE child2_tbl() INHERITS(parent_tbl); 
CREATE TABLE child3_tbl() INHERITS(parent_tbl); 

ALTER TABLE child2_tbl NO INHERIT parent_tbl; 
ALTER TABLE child2_tbl INHERIT parent_tbl; 

ALTER TABLE parent_tbl DROP COLUMN f2; 

\d child*_tbl 

            Table "public.child1_tbl" 
Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+--------- 
f1     | integer |           |          | 
f3     | integer |           |          | 
Inherits: parent_tbl 

            Table "public.child2_tbl" 
Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+--------- 
f1     | integer |           |          | 
f2     | integer |           |          | 
f3     | integer |           |          | 
Inherits: parent_tbl 

            Table "public.child3_tbl" 
Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+--------- 
f1     | integer |           |          | 
f3     | integer |           |          | 
Inherits: parent_tbl 

#73 Re : Migration » Dans Select utiliser Aliasnom = Champ au lieu Champ AS Aliasnom » 16/02/2022 18:16:19

Non ça n'existe pas. D'ailleurs nomclient = clinom est valide comme expression pour une colonne dans Postgres, donc ça poserait un problème d'ambiguité (ça renvoie un booléen valant le résultat du test d'égalité entre nomclient et clinom).

#74 Re : Sécurité » Connexion via .pgpass » 18/01/2022 11:31:33

Il est aussi possible que le mot de passe soit hashé en md5 alors que le serveur requiert scram-sha-256 via pg_hba.conf.
Il me semble que c'est le message d'erreur générique de mot de passe incorrect qui sort dans ce cas-là.


Pour faire la transition md5 -> scram-sha-256, il faut vérifier que password_encryption est bien à "scram-sha-256" et regénérer le mot de passe avec la commande \password de psql, pour chaque compte ayant un "vieux" mot de passe.

#75 Re : Sécurité » lo_compat_privileges » 13/01/2022 13:54:32

L'alternative, c'est de donner des droits de lecture à chaque large object créé, avec

GRANT SELECT  ON LARGE OBJECT loid  TO role; 

C'est le possesseur de l'objet ou un superutilisateur qui doit donner ces droits.

L'oid est juste le numéro de l'objet. Le fait de pouvoir lire le numéro ou pas est complètement déconnecté du fait de pouvoir lire/écrire l'objet ou pas avec les fonctions dédiées lo*

Pied de page des forums

Propulsé par FluxBB