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).

#1 29/11/2014 10:20:14

krile
Membre

SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Bonjour

Nous constatons une déperdition importante de performance entre la 8.4 et la 9.3 sur le lock explicite

Nous travaillons sur une table nommée "chrono" pour l'exemple, qui contient moins de 50 lignes

Le code concerné est le suivant :
-----------------------------------------------------
begin
for 1 to 1000
    select * from chrono  where [where_condition] FOR UPDATE
    do stuff (or not…..)
    update chrono set [set_clause] where [where_condition]
end for
commit
--------------------------------------------------------
En 8.4, no problem: le temps de chaque boucle reste homogène, du début à la fin.
En 9.3, il y a une déperdition exponentielle !

Nos tests montrent qu'une façon "simple" de résoudre le problème serait de faire un commit après chaque update de chrono, afin de "libréer" le lock.
Mais, mais, mais: faire cela a d'énormes conséquences par ailleurs, sur notre application (pour faire simple, une réécriture très lourde, chronophage et impactante)

Une idée ou une explication ?

Merci

Dernière modification par krile (29/11/2014 11:09:03)

Hors ligne

#2 29/11/2014 19:12:57

gleu
Administrateur

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Un test très rapide de mon côté indique les mêmes durées entre une 8.4 et une 9.3. 600ms dans le cas de la transaction globale, et 9s dans le cas des transactions unitaires. Bref, rien de bien nouveau. Il doit y avoir quelque chose de spécifique à votre application que vous n'avez pas partagé avec nous.


Guillaume.

Hors ligne

#3 01/12/2014 11:19:01

krile
Membre

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Bonjour, et merci pour cette réponse,

La déperdition se manifeste avec une nombre d'itérations > 1000, voire > 10 000. La déperdition semble alors exponentielle.

Voici le code utilisé, et exécuté directement via pgadmin, sur une base identique 8.4 et 9.3.
La procédure est lancée via un "select * from jpi_test_perf_chronos()" tout simple
A noter que les tables etablissement et  param_chrono contiennent moins de 50 enreg :

---------------------------------------------------------

CREATE OR REPLACE FUNCTION jpi_test_perf_chronos()
  RETURNS VOID AS
$BODY$
DECLARE
  x INTEGER := 0;
  y INTEGER;

 
BEGIN

  LOOP
       select 1 from param_chrono into y where chron_table = 'facture' for UPDATE;


    select 1 into y from etablissement limit 1;

   
    update param_chrono set chron_chrono = chron_chrono where chron_table = 'facture';

    x := x +1 ;
   
    IF x >= 9999 THEN 
        EXIT;
     END iF ;
   
  END LOOP;

RETURN;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
------------------------------------------------------------------------------

En 8.4 =>  4300 ms
En 9.3 =>  19 500 ms   (...)

Dernière modification par krile (01/12/2014 11:41:13)

Hors ligne

#4 01/12/2014 12:57:29

gleu
Administrateur

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

J'ai fait de nouveau un test sur mon portable avec ce script :

create database test;

\c test

create language plpgsql;
CREATE TABLE param_chrono (chron_table text, chron_chrono integer);
INSERT INTO param_chrono SELECT 'facture', i FROM generate_series(1, 10) AS i;
CREATE TABLE etablissement ();

CREATE OR REPLACE FUNCTION f1()
  RETURNS VOID AS
$BODY$
DECLARE
  x INTEGER := 0;
  y INTEGER;
BEGIN
  LOOP
    select 1 from param_chrono into y where chron_table = 'facture' for UPDATE;
    select 1 into y from etablissement limit 1;

    update param_chrono set chron_chrono = chron_chrono where chron_table = 'facture';

    x := x +1 ;
   
    IF x >= 9999 THEN 
      EXIT;
    END IF;
  END LOOP;

  RETURN;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
\timing
SELECT f1();
SELECT f1();
SELECT f1();

Les résultats en 8.4 :
Time: 28289.002 ms
Time: 33390.830 ms
Time: 24323.990 ms

Les résultats en 9.3 :
Time: 30775.129 ms
Time: 43561.052 ms
Time: 39700.712 ms


Guillaume.

Hors ligne

#5 01/12/2014 17:47:18

krile
Membre

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

De mon côté, en utilisant le même code que vous (et les mêmes tables)

8.4 :
--27 550
--36 318
--32 589
--33 010
--38 720
--56 379
--43 696
--28 704
--29 031
--34 710

9.3 :
--53 758
--44 179
--39 110
--37 503
--51 059
--68 345
--62 526
--41 372
--43 275

Je ne suis pas sur que l'on puisse en tirer quoi que ce soit. Éventuellement que cela est quand-même plus long en 9.3.


Ceci étant dit, nous avons trouvé l'explication à la dégradation exponentielle que nous constations en 9.3. Il s'agissait d'une différence entre les deux postgres.conf

Bref, pour conclure sur la batterie de tests du jour :
- la 9.3 reste plus lente sur la gestion de slock explicite
- la dégradation exponentielle se corrige via "bon" paramétrage du postgres.conf

Hors ligne

#6 01/12/2014 20:06:59

nterrien
Membre

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Pour compléter ce qui a été dit plus haut (étant un collègue de krile) :
Nos tests ont été faits sur Windows (7, 64 bits), avec des version 9.3 32 bits et 64 bits, ainsi que 9.4 RC1 (64 bits).

Hors ligne

#7 01/12/2014 20:48:34

gleu
Administrateur

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Il serait intéressant de savoir quelle était la mauvaise configuration, et quelle était la bonne configuration...


Guillaume.

Hors ligne

#8 02/12/2014 03:47:58

krile
Membre

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Finalement, fausse joie !
Les derniers tests n'étaient pas probants, notamment concernant la perte exponentielle que nous ne constations plus.
En effet, nous n'avions plus, dans notre jeu de test, de ligne concernée par le select for update (sic)

Le problème reste donc entier.

Hors ligne

#9 02/12/2014 15:21:49

nterrien
Membre

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

@Gleu : le problème n'est pas résolu mais la cause est trouvée : il s'agit du pilote ODBC.

En accès direct : pas de problème (que nous ne pouvons pas utiliser dans notre application, je passe les détails).

Avec le pilote ODBC (unicode, version 8.4.2 et 9.3.4) vs PG 8.4 : pas de problème.

Même application, même pilotes ODBC (v8.4.2 ou v9.3.4) vs PG 9.3 ou 9.4 RC1 : augmentation exponentielle du temps de traitement dans le cas décrit ci-dessus.

Dernière modification par nterrien (02/12/2014 15:22:26)

Hors ligne

#10 02/12/2014 15:58:31

gleu
Administrateur

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Là, il faudrait voir directement avec les développeurs de psqlodbc. Je ne connais pas assez pou rêtre d'une quelconque aide.


Guillaume.

Hors ligne

#11 02/12/2014 17:10:40

nterrien
Membre

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Oui, c'est que l'on s'est dit aussi.
Merci pour le coup de main en tout cas !

Hors ligne

#12 05/12/2014 22:39:10

gleu
Administrateur

Re : SELECT FOR UPDATE : problème de performance entre 8.4 et 9.3

Donc le problème a été rapporté sur la liste psqlodbc : http://www.postgresql.org/message-id/52 … matique.fr

La solution a été trouvée par Heikki, suite à une idée d'Alvaro : http://www.postgresql.org/message-id/54 … vmware.com (passé en protocole 7.4-0 pour éviter l'ajout de SAVEPOINT qui ont un coût assez fort dans l'exécution d'une transaction).


Guillaume.

Hors ligne

Pied de page des forums