Voir le flux RSS

Gugelhupf

[Actualité] Benchmark PostgreSQL vs MySQL

Noter ce billet
par , 22/06/2015 à 18h54 (2619 Affichages)
Le document qui suit est un extrait du benchmark PostgreSQL 9.3.5 vs MySQL 5.5.40 que j’ai réalisé dans le cadre du projet de synthèse (étude). Son contenu est comme chaque benchmark contestable.

Les benchmarks ont entièrement étés réalisés sous les machines virtuelles de l’Esiag :
  • OS : Linux 3.13 | distribution Ubuntu Server 14.04 LTS 64 bits.
  • RAM : 8 Go.

CPU Intel (cf : commande lscpu)
  • Fréquence : 2.00 Ghz
  • Nombre de cœur : 4
  • Architecture : x86_64
  • Byte Order : Little Endian


Afin de ne pas influencer les résultats du benchmark, tous les tests liés aux bases relationnelles ont étés effectués à partir d’un OS Linux sans interface graphique :
  • Pour PostgreSQL je me suis servi du client psql et de la fonctionnalité « EXPLAIN ANALYZE ».
  • Pour MySQL je me suis servi du client mysql et de la fonctionnalité « SET PROFILING = 1 ».


Dimensionnement : Les HealthNet souhaitent une base pouvant gérer 1M de patients pour 4000 médecins. Nous allons donc effectuer des tests d’écriture et de lecture afin de déterminer la base relationnelle la plus adaptée par rapport à nos besoins Durée & FURPS PostgreSQL 9.3.5 MySQL 5.5.40
(InnoDB engine)
A1: Durée d’insertion des 4000 médecins dans la base (my_proc1) Durée en ms 254.646 6860.102
FURPS = 500 ms
1 - (X / 500)
49.07% -1272.02%
A2: Durée d’insertion de 1M de patients dans la base (my_proc2) Durée en ms 21936.422 25 min 4.53 sec
FURPS = 125000 ms
1 - (X / 125000)
82.45% DEAD
A3: Durée d’attribution des médecins pour chaque patient (insertion dans la table charnière) (my_proc3) Durée en ms 58830.697 23 min 51.62 sec
FURPS = 125000 ms
1 - (X / 125000)
52.94% DEAD
A4: Durée pour récupérer l’ensemble des patients (1M) ainsi que leurs médecins Durée en ms 2995.391 19320.937
FURPS = 4000 ms
1 - (X / 4000)
25.12% -383.02%
A5: Durée pour récupérer les patients d’1 médecin Durée en ms 222.573 13.505
FURPS = 500 ms
1 - (X / 500)
55.49% 97.30%
A6: Durée pour récupérer les 10 médecins ayant le plus de patients (utilisation de fonction d’agrégat) Durée en ms 404.421 1041.214
FURPS = 500 ms
1 - (X / 500)
19.12% -108.24%


Analyse du tableau : Les trois premiers tests sont axés sur de l’écriture dans la base, les trois suivantes sur de la lecture.

Concernant l’écriture, PostgreSQL est très rapide et les performances affichées par MySQL sont juste aberrantes.

Concernant la lecture :
  • A4 : On peut remarquer que pour la lecture d’un grand nombre de tuples (1M), PostgreSQL affiche des performances bien supérieures à MySQL.
  • A5 : A contrario, sur des petites quantités de données à récupérer, MySQL est plus rapide que PostgreSQL.
  • A6 : Les performances affichés par PostgreSQL sont bien meilleures que celle de MySQL lors de l’utilisation des fonctions d’agrégats.


De par la qualité de sa documentation, la robustesse et les performances qu’elle propose, PostgreSQL semble être la solution la plus adaptée aux besoins de nos utilisateurs, c’est la raison pour laquelle PostgreSQL devrait être un composant de notre solution de PAAS.


NB : Les scripts utilisés ainsi que les screens des clients psql et mysql sont présents dans l’Annexe A,


Annexe A : Bases relationnelles

Création des tables, index, contraintes référentielles (requêtes standard SQL, compatible PostgreSQL et MySQL) :
Table médecin
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
CREATE TABLE t_medecin(
    id int,
    nom varchar(50),
    prenom varchar(50),
    mail varchar(50),
    specialite int
);
 
ALTER TABLE t_medecin ADD CONSTRAINT pk_medecin PRIMARY KEY (id);
Table patient
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
CREATE TABLE t_patient(
    id int,
    nom varchar(50),
    prenom varchar(50),
    mail varchar(50)
);
 
ALTER TABLE t_patient ADD CONSTRAINT pk_patient PRIMARY KEY (id);
Table charnière médecin/patient
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
CREATE TABLE t_charniere_medecin_patient(id_medecin int, id_patient int);
 
ALTER TABLE t_charniere_medecin_patient ADD CONSTRAINT fk_id_medecin
FOREIGN KEY (id_medecin) REFERENCES t_medecin(id);
 
ALTER TABLE t_charniere_medecin_patient ADD CONSTRAINT fk_id_patient
FOREIGN KEY (id_patient) REFERENCES t_patient(id);


Fonction permettant de générer un nombre aléatoire entre 2 valeurs :
PostgreSQL 9.3.5 MySQL 5.5.40
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
-- start_range  inclusive | end_range exclusive
CREATE FUNCTION random_range_int(start_range int, end_range int)
RETURNS INTEGER AS $$
BEGIN
    RETURN trunc(random() * (end_range - start_range) + start_range);
END;
$$ LANGUAGE plpgsql;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
-- start_range  inclusive | end_range inclusive
DELIMITER $$
CREATE FUNCTION random_range_int(start_range INTEGER, end_range INTEGER)
RETURNS int
BEGIN
    RETURN round(rand() * (end_range - start_range) + start_range);
END $$
DELIMITER ;



Requête des tests :
Test PostgreSQL 9.3.5 MySQL 5.5.40
Note SET profiling = 1;
A1
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
CREATE FUNCTION my_proc1()
RETURNS void
AS $$
    FOR i IN 1..4000 LOOP
        INSERT INTO t_medecin(id, nom, prenom, mail, specialite)
        VALUES(i, 'Nom ' || i, 'Prenom ' || i, '@mail ' || i, random_range_int(1, 9));
    END LOOP;
END;
$$ LANGUAGE plpgsql;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
CREATE PROCEDURE my_proc1()
BEGIN
    DECLARE i INT DEFAULT 1;   
    WHILE i <= 4000 DO
        INSERT INTO t_medecin(id, nom, prenom, mail, specialite)
        VALUES(i, CONCAT('Nom ', i), CONCAT('Prenom ', i), CONCAT('@mail ', i), random_range_int(1, 8));
        SET i = i + 1;
    END WHILE;
END $$
DELIMITER ;
A2
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
CREATE FUNCTION my_proc2()
RETURNS void
AS $$
    FOR i IN 1..1000000 LOOP
        INSERT INTO t_patient(id, nom, prenom, mail)
        VALUES(i, 'Nom ' || i, 'Prenom ' || i, '@mail ' || i);
    END LOOP;
END;
$$ LANGUAGE plpgsql;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
CREATE PROCEDURE my_proc2()
BEGIN   
    DECLARE i INT DEFAULT 1;
    WHILE i <= 1000000 DO
        INSERT INTO t_patient(id, nom, prenom, mail)
        VALUES(i, CONCAT('Nom ', i), CONCAT('Prenom ', i), CONCAT('@mail ', i));
        SET i = i + 1;
    END WHILE;
END $$
DELIMITER ;
A3
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
CREATE FUNCTION my_proc3()
RETURNS void
AS $$
    FOR i IN 1..1000000 LOOP
        INSERT INTO t_charniere_medecin_patient(id_medecin, id_patient)
        VALUES(random_range_int(1, 4001), i);
    END LOOP;
END;
$$ LANGUAGE plpgsql;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
CREATE PROCEDURE my_proc3()  
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i <= 1000000 DO
        INSERT INTO t_charniere_medecin_patient(id_medecin, id_patient)
        VALUES(random_range_int(1, 4000), i);
        SET i = i + 1;
    END WHILE;
END $$
DELIMITER ;
A4
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
EXPLAIN ANALYZE
SELECT
    P.*,
    M.nom AS nom_medecin,
    M.prenom AS prenom_medecin
FROM t_medecin M
JOIN t_charniere_medecin_patient MP
ON M.id = MP.id_medecin
JOIN t_patient P
ON P.id = MP.id_patient;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
SELECT
    P.*,
    M.nom AS nom_medecin,
    M.prenom AS prenom_medecin
FROM t_medecin M
JOIN t_charniere_medecin_patient MP
ON M.id = MP.id_medecin
JOIN t_patient P
ON P.id = MP.id_patient;
A5
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
EXPLAIN ANALYZE
SELECT
    P.*,
    M.nom AS nom_medecin,
    M.prenom AS prenom_medecin
FROM t_medecin M
JOIN t_charniere_medecin_patient MP
ON M.id = MP.id_medecin
JOIN t_patient P
ON P.id = MP.id_patient
WHERE M.id  = 40;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
SELECT
    P.*,
    M.nom AS nom_medecin,
    M.prenom AS prenom_medecin
FROM t_medecin M
JOIN t_charniere_medecin_patient MP
ON M.id = MP.id_medecin
JOIN t_patient P
ON P.id = MP.id_patient
WHERE M.id  = 40;
A6
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
EXPLAIN ANALYZE
SELECT
    MP.id_medecin,
    COUNT(*) AS c
FROM t_charniere_medecin_patient MP
GROUP BY MP.id_medecin
ORDER BY c
DESC LIMIT 10;
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
SELECT
    MP.id_medecin,
    COUNT(*) AS c
FROM t_charniere_medecin_patient MP
GROUP BY MP.id_medecin
ORDER BY c
DESC LIMIT 10;



Schéma : ANALYZE EXPLAIN PostgreSQL (A4)




Schéma : ANALYZE EXPLAIN PostgreSQL (A5)



Schéma : ANALYZE EXPLAIN PostgreSQL (A6)



Schéma : SHOW PROFILES MySQL (La 1ère flèche rouge représente A4, la 2ème A5, et la 3ème A6)


Que pensez-vous de ce benchmark ?
Selon vous, comment pourrais-t-on améliorer ce benchmark ?

Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Viadeo Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Twitter Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Google Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Facebook Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Digg Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Delicious Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog MySpace Envoyer le billet « Benchmark PostgreSQL vs MySQL » dans le blog Yahoo

Mis à jour 24/04/2016 à 20h41 par LittleWhite (Coloration code)

Catégories
Sans catégorie

Commentaires

  1. Avatar de kolodz
    • |
    • permalink
    C'est normal qu'on ne voit pas de déclaration d'index ? Car, quand on constat des temps dépassant très largement la seconde sur une base de donnée, c'est qu'on a un problème. Et dans le cas présenté, il n'y a absolument aucun index ce qui n'est pas normal.

    Du coup, si l'un crée automatiquement des index et l'autre non... Tu favorise très fortement l'un pour cette unique raison...

    Et comme tu le dit toi-même :
    Concernant l’écriture, PostgreSQL est très rapide et les performances affichées par MySQL sont juste aberrantes.
    Donc avant d'aller plus loin la réalisation d'un bench, il est nécessaire de savoir pourquoi tu as ces résultats. MySQL n'étant pas un SGBD qui débarque du ciel et qui n'est jamais utilisé...

    Cordialement,
    Patrick Kolodziejczyk.
  2. Avatar de Gugelhupf
    • |
    • permalink
    Citation Envoyé par kolodz
    C'est normal qu'on ne voit pas de déclaration d'index ? Car, quand on constat des temps dépassant très largement la seconde sur une base de donnée, c'est qu'on a un problème. Et dans le cas présenté, il n'y a absolument aucun index ce qui n'est pas normal.

    Du coup, si l'un crée automatiquement des index et l'autre non... Tu favorise très fortement l'un pour cette unique raison...
    Les contraintes de clé primaire et référentielle sont juste en dessous de la création des tables :
    • PostgreSQL crée implicitement des index pour les clés primaires => tables t_medecin (cas A1) et t_patient (cas A2)
    • MySQL crée implicitement des index pour les clés primaires, et référentielles pour InnoDB (ce qui est notre cas) => t_medecin (cas A1) et t_patient (cas A2) et t_charniere_medecin_patient (cas A3).

    Cela n'explique pas pourquoi pour le cas de A1 et A2 PostgreSQL est plus rapide que MySQL vu qu'ils ont tout les deux des index.
    Cela n'explique pas non plus pourquoi pour le cas A3 PostgreSQL prend plus de temps par rapport à MySQL par rapport au cas A2 vu que PostgreSQL ne possède pas d'index et que MySQL si.
    Je ne pense pas favoriser l'un par rapport à l'autre sur les index, mais les cas que je montre favorisent PostgreSQL sur sa polyvalence. Si j'avais voulu favoriser MySQL, je n'aurais que fait des requêtes de type SELECT sur des petites quantités de donnée.

    Cordialement,
  3. Avatar de kolodz
    • |
    • permalink
    On parle de MySQL et PostgreSQL. C'est deux SGBD sont très rependu et maintenu depuis des années. Il est largement plus probable que ton cas de test ne soit pas correcte.
    Très probablement parce que ces deux SGBD n'ont pas la même configuration par défaut.

    De plus tu ne test pas les mêmes fonctionnalité entre PostgreSQL où A1, A2 et A3 sont des fonctions et en MySQL tu utilise des procédures. Sachant qu'il est possible de crée des fonctions en MySQL.

    Donc, sans même remettre en cause l'installation, tu ne demande pas la même chose au deux bases de données. Donc avant de remettre en cause directement le SGBD, j’irai voir dans les différences...

    Cordialement,
    Patrick Kolodziejczyk.
  4. Avatar de Gugelhupf
    • |
    • permalink
    Citation Envoyé par kolodz
    De plus tu ne test pas les mêmes fonctionnalité entre PostgreSQL où A1, A2 et A3 sont des fonctions et en MySQL tu utilise des procédures. Sachant qu'il est possible de crée des fonctions en MySQL.
    Il s'agit pour PostgreSQL et de MySQL de procédure. Pour créer une procédure avec PostgreSQL on doit utiliser la syntaxe CREATE FUNCTION ... RETURNS void. Et puis une fonction n'est rien d'autre qu'une procédure qui retourne une valeur, cela ne doit pas justifier les performances plus qu’aberrante de MySQL en écriture.


    Citation Envoyé par kolodz
    Donc, sans même remettre en cause l'installation, tu ne demande pas la même chose au deux bases de données. Donc avant de remettre en cause directement le SGBD, j’irai voir dans les différences...
    Au contraire, on peut remettre en cause l'installation, car j'ai laissé les paramètres par défaut lors de l'installation avec apt-get, cependant je demande bien la même choses aux deux SGBD.

    Cordialement,
    Mis à jour 23/06/2015 à 12h21 par Gugelhupf
  5. Avatar de kolodz
    • |
    • permalink
    Citation Envoyé par Gugelhupf
    Il s'agit pour PostgreSQL et de MySQL de procédure. Pour créer une procédure avec PostgreSQL on doit utiliser la syntaxe CREATE FUNCTION ... RETURNS void. Et puis une fonction n'est rien d'autre qu'une procédure qui retourne une valeur, cela ne doit pas justifier les performances plus qu’aberrante de MySQL en écriture.
    Tu ne peux pas affirmer de manière sur que MySQL/PostgreSQL gère de la même manière les procédures et les fonctions. D'ailleurs, cela me semblerai logique qu'il y ai des différences dans le comportement et dans leur gestion.

    Citation Envoyé par Gugelhupf
    Au contraire, on peut remettre en cause l'installation, car j'ai laissé les paramètres par défaut lors de l'installation avec apt-get, cependant je demande bien la même choses aux deux SGBD.

    Cordialement,
    Si tu ne réalise pas les mêmes requêtes mot pour mot, tu ne leur demande pas la même chose. Il faut être très prudent par rapport au différentes fonctionnalités et leur implémentation. J'ai déjà vue des optimisations être réalisées sur un ordre de paramètre et pas sur un autre. Donc temps que tu ne lance pas le même script sur les deux base tu ne test pas la même chose.

    En suite, la premier chose qui me perturbe, c'est l’insertion ligne à ligne. Pour un grand set de data, cela n'est pas une bonne idée. Car, MySQL va vouloir mettre à jour ses index à chaque fin d'insertion par exemple.

    J'ai rapidement testé l'insertion des lignes par bloque de 1000 lignes :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    INSERT INTO t_patient(id, nom, prenom, mail) VALUES  (1, 1, 1, 1),
     (2, 2, 2, 2),
     (3, 3, 3, 3),
    //...
     (998, 998, 998, 998),
     (999, 999, 999, 999),
     (1000, 1000, 1000, 1000);
    Via un ficher en dur. Sans utilisation de fonction annexe tel contact(). Le bût étant d'éviter de mesure ces fonctions à la place du reste. En particulier, quand l'implémentation de ces fonctions n'est pas la même entre tes deux benchs (MySQL a son implémentation PostgreSQL en a une autre)

    La durée d'insertion d'un bloque de 1000 ligne est de 0.01 sec à 0.07 sec chez moi. Ce qui fait pour les 1 millions de lignes voulu une durée de 70 secondes maximum, ce qui est très loin de ton "25 min 4.53 sec" constaté.
    Cela est d'ailleurs documenté ici :
    https://dev.mysql.com/doc/refman/5.0...ert-speed.html


    Peut-être désactivé les index pendant l'import du jeu de donnée :
    https://support.tigertech.net/mysql-...able-mysql-jmp
    Qui indique l'utilisation de ceci :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    -- avant l'appel de la procédure
    SET FOREIGN_KEY_CHECKS = 0;
    SET UNIQUE_CHECKS = 0;
    SET AUTOCOMMIT = 0;
    -- après l'appel de la procédure
    SET FOREIGN_KEY_CHECKS = 1;
    SET UNIQUE_CHECKS = 1;
    SET AUTOCOMMIT = 1;
    Et du coup on a :
    Citation Envoyé par Retour console
    mysql> SET FOREIGN_KEY_CHECKS = 0;
    Query OK, 0 rows affected (0.00 sec)

    mysql> SET UNIQUE_CHECKS = 0;
    Query OK, 0 rows affected (0.00 sec)

    mysql> SET AUTOCOMMIT = 0;
    Query OK, 0 rows affected (0.00 sec)

    mysql> call my_proc2();
    Query OK, 1 row affected (20.70 sec)

    mysql> SET AUTOCOMMIT = 0;SET UNIQUE_CHECKS = 1;
    Query OK, 0 rows affected (0.00 sec)

    Query OK, 0 rows affected (0.00 sec)

    mysql> SET FOREIGN_KEY_CHECKS = 1;
    Query OK, 0 rows affected (0.00 sec)

    mysql> COMMIT;
    Query OK, 0 rows affected (0.05 sec)

    Note : Personnellement, la conclusion d'un bench entre deux SGBD connu ne peux pas être "Il y en a un qui fait de la merde", il faut au moins donner une justification. Il y a d'ailleurs une publication qui avait réalisé un bench sur l'écriture de ficher en Java VS C. Sans comprendre que la concaténation de string Java crée un nouvelle objet en mémoire à chaque fois. Du coup, il ne mesuraient pas ce qu'il fallait... (Le papier s'étaient fait allumé par la communauté Java et C...)

    Cordialement,
    Patrick Kolodziejczyk.

    EDIT : Du coup, A1, A2 et A3 ont les mêmes performances, si tu réalise tes insertions proprement. (insertion multiple, non mise à jour des index pendant les insertions.)
    Et si tu crée réellement test index A6 sera beaucoup plus efficace :

    Citation Envoyé par Retour console
    CREATE INDEX i_charniere_medecin_patient_id_medecin ON t_charniere_medecin_patient (id_medecin);
    Query OK, 0 rows affected (7.64 sec)
    Records: 0 Duplicates: 0 Warnings: 0

    mysql>
    mysql> SELECT
    -> MP.id_medecin,
    -> COUNT(*) AS c
    -> FROM t_charniere_medecin_patient MP
    -> GROUP BY MP.id_medecin
    -> ORDER BY c
    -> DESC LIMIT 10;
    +------------+-----+
    | id_medecin | c |
    +------------+-----+
    | 1894 | 577 |
    | 1597 | 576 |
    | 3807 | 574 |
    | 1680 | 574 |
    | 2512 | 571 |
    | 2067 | 570 |
    | 1077 | 567 |
    | 86 | 566 |
    | 2918 | 565 |
    | 3851 | 565 |
    +------------+-----+
    10 rows in set (0.78 sec)
    Note : J'ai joué deux fois my_proc3(). Ce qui fait que j'ai 2 fois plus de lignes que toi. Et, il n'y a pas clé unique sur l’association id_patient/id_medecin, ce qui est déjà un problème en soit. Je ne parle même pas des auto-incrément qui ne sont pas utilisé pour les ID.
    Mis à jour 23/06/2015 à 15h40 par kolodz
  6. Avatar de Gugelhupf
    • |
    • permalink
    Citation Envoyé par kolodz
    Tu ne peux pas affirmer de manière sur que MySQL/PostgreSQL gère de la même manière les procédures et les fonctions. D'ailleurs, cela me semblerai logique qu'il y ai des différences dans le comportement et dans leur gestion.
    Je n'affirme rien, cependant la différence de temps entre les deux SGBD est trop importante pour qu'il puisse juste s'agir d'une simple question de procédure ou "fonction qui ne retourne pas de valeur". Je pense avoir trouvé d'où vient cette grosse différence et qui me poussera peut-être à refaire le benchmark (lire plus bas).


    Citation Envoyé par kolodz
    Si tu ne réalise pas les mêmes requêtes mot pour mot, tu ne leur demande pas la même chose. Il faut être très prudent par rapport au différentes fonctionnalités et leur implémentation. J'ai déjà vue des optimisations être réalisées sur un ordre de paramètre et pas sur un autre. Donc temps que tu ne lance pas le même script sur les deux base tu ne test pas la même chose.
    MySQL fournit la fonction spécifique CONCAT() et PostgreSQL implémente l'opérateur standard || pour la concaténation. Impossible de demander un même résultat avec une syntaxe identique si l'un implémente et pas l'autre. Sachant qu'il n'y a pas d'alternative on peut considérer cela comme un simple détail.


    Citation Envoyé par kolodz
    En suite, la premier chose qui me perturbe, c'est l’insertion ligne à ligne. Pour un grand set de data, cela n'est pas une bonne idée. Car, MySQL va vouloir mettre à jour ses index à chaque fin d'insertion par exemple.

    J'ai rapidement testé l'insertion des lignes par bloque de 1000 lignes :
    [...]
    Via un ficher en dur. Sans utilisation de fonction annexe tel contact(). Le bût étant d'éviter de mesure ces fonctions à la place du reste. En particulier, quand l'implémentation de ces fonctions n'est pas la même entre tes deux benchs (MySQL a son implémentation PostgreSQL en a une autre)
    L'objectif n'était peut-être pas de faire une insertion multiple, mais plusieurs insertions distincts. Pour en revenir à la différence de temps considérable, l'erreur que je commet est qu'une procédure/fonction PostgreSQL démarre implicitement une transaction, MySQL lui requiert que la transaction soit explicitement écrite (donc chaque insertion MySQL équivaut à faire un COMMIT). La solution serait donc de faire un START TRANSACTION en début de procédure et COMMIT en fin de procédure pour avoir un résultat équivalent.


    Cordialement,
  7. Avatar de kolodz
    • |
    • permalink
    MySQL fournit la fonction spécifique CONCAT() et PostgreSQL implémente l'opérateur standard || pour la concaténation. Impossible de demander un même résultat avec une syntaxe identique si l'un implémente et pas l'autre. Sachant qu'il n'y a pas d'alternative on peut considérer cela comme un simple détail.
    Sachant que les deux SGBD ont une implémentation correcte oui. Cependant, il serai préférable d'avoir un jeu de donnée identique pour les deux bases de données. Surtout pour les requêtes A4 et A5 où le nombre de ligne à retrouver dans t_medecin sera différents. (et donc un temps de réponse différents.)

    Note : le temps de réponse sur les requêtes A4 et A5 est très probablement aussi impacté par la présence d'un index sur la table t_charniere_medecin_patient. Car, il est plus facile de faire une jointure sur des données déjà indexé.

    L'objectif n'était peut-être pas de faire une insertion multiple, mais plusieurs insertions distincts.
    Tes premières requêtes sont là pour crée une base de donnée de test. Il n'arrivera jamais dans la vie courante de ta base de donnée un cas où tu va faire un millions de l'insertion en un seul coup. Sachant que si tu fait un dump de ta base de données tes insertions seront des insertions multiple. Ce cas n'est donc pas sensé se produire.
    Sauf si tu parle de l'activité courante de ta base de donnée sur plusieurs années. Et à ce moment là c'est le temps de réponse moyen sur une insertion qui compte. Or ce n'est pas ce que tu mesure, au minimum sur PostgreSQL.

    Note : Dans tout les cas, ton bench va nécessairement indiqué que les deux solutions sont viable si correctement utilisé. Les deux étant utilisées à des échelles très largement supérieur à ce que tu réalise dans ton test. Tout autre réponse serai ridicule, c'est (pratiquement) des standard dans l'industrie. De mémoire amazone et pirateBay utilisent/utilisaientt MySQL

    Cordialement,
    Patrick Kolodziejczyk.
  8. Avatar de Gugelhupf
    • |
    • permalink
    Houlala mon article a été publié sur le rubrique SQL, je vais me faire taper dessus par les MySQL-iens. Qu'on soit d'accord, les parties A1, A2 et A3 axés sur l'écriture n'est pas bon à cause de l’absence de bloc transactionnelle pour MySQL.
    A4, A5 et A6 axés sur la lecture sont déjà plus plausibles (si on ne prend pas en compte le fait que les champs ont étés remplies de manière aléatoire ) .
  9. Avatar de kolodz
    • |
    • permalink
    Lien ?
    Edit : (http://sgbd.developpez.com/actu/8732...par-Gugelhupf/)
    Inclus ce post ^^
    Mis à jour 06/07/2015 à 17h36 par kolodz
  10. Avatar de SQLpro
    • |
    • permalink
    MySQL ne dispose pas d'un cache des procédure qui permet la réutilisation des plans de requête et donc de réutiliser les plans mis en cache.

    PostGreSQL ne dispose pas d'un CREATE PROCEDURE, mais en fait le CREATE FUNCTION est la création d'une procédure stockée pouvant indifféremment fournir une valeur scalaire (UDF) ou un ou jeu de résultat (dataset) ou bien encore juste un code de retour (erreur) et dans ce cas c'est l'équivalent d'une procédure.
    Seule particularité, PostGreSL ne permet pas de définir les frontière d'une transaction à travers les FUNCTION (BEGIN WORK, COMMIT, ROLLBACK), étant entendu que dans PG, toute fonction est par nature traditionnellement atomique.

    J'ajouterais que le niveau très faible de SQL de la part de MySQL (pas de CTE, pas de fonctions de fenêtrage, etc...) le rend rsè peu performant, comme je l'ai montré ici :
    http://blog.developpez.com/sqlpro/p9...alles_en_sql_1

    A +