par
Ripat » 21 janv. 2009, 11:35
Bonjour,
Je suis en cours de test comparatif pour les trois SGBD en sujet. Ce test n'a absolument pas de valeur scientifique. Juste un petit test empirique pour démystifier les lieux communs. Vous pouvez vous même faire ce test avec le code donné plus bas.
Je viens de terminer la première phase: insertion de données. Le reste suivra au fur et à mesure.
Méthodologie:
- Utilisation de la classe d'abstraction PDO (encore heureux qu'elle existe!)
- Utilisation des "prepared statement" c'est à dire la compilation côté serveur d'une requête répétitive
- Utilisation des transactions si elles sont supportées (BEGIN ... COMMIT)
- Insertion de 10.000 chaînes aléatoires sur 4 colonnes.
- Test d'insertions concurrentes en lançant des processus d'insertion concurrents
- Serveur de test: hors charge, Pentium 4 2.4 Ghz - 768 MB ram - Linux Debian.
- PHP 5.2 (avec extension PDO), Mysql 5.0, SQLite 3.3, Postgres 8.2
Code du test:
/* production des chaînes aléatoires à insérer */
for ($i = 0; $i < 10000; $i++){
$aCol1[$i] = md5(mt_rand(1, 5000));
$aCol2[$i] = md5(mt_rand(1, 5000));
$aCol3[$i] = md5(mt_rand(1, 5000));
$aCol4[$i] = md5(mt_rand(1, 5000));
}
/* Paramètres des bdd et types de tables*/
$aDbs = array(
'SQLite' => '',
'Postgr' => '',
'MyISAM' => 'ENGINE=MyISAM',
'InnoDB' => 'ENGINE=InnoDB',
);
foreach ($aDbs as $dbType => $engine){
/* Connexion PDO aux bdd */
if ($dbType == 'SQLite'){
$pdo = new PDO('sqlite:/var/lib/sqlite/test.sqlite3');
} elseif ($dbType == 'Postgr'){
$pdo = new PDO('pgsql:host=localhost dbname=test user=****** password=********');
} else {
$pdo = new PDO('mysql:dbname=test;host=localhost', '****', '*******');
}
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
/* RAZ et création d'une table */
$qry = 'DROP TABLE IF EXISTS table1';
$pdo->exec($qry);
$qry = 'CREATE TABLE table1 ( col1 VARCHAR(50), col2 VARCHAR(50), col3 VARCHAR(50), col4 VARCHAR(50)) '.$engine;
$pdo->exec($qry);
/* Insertion: préparation et exécution */
$time_start = microtime(true);
$insert = "INSERT INTO table1 (col1, col2, col3, col4) VALUES (:val1, :val2, :val3, :val4)";
$result = $pdo->prepare($insert);
$pdo->beginTransaction();
foreach ($aCol1 as $k => $v){
$result->execute(array(':val1' => $aCol1[$k], ':val2' => $aCol2[$k], ':val3' => $aCol3[$k], ':val4' => $aCol2[$k]));
}
$pdo->commit();
$time_end = microtime(true);
echo $dbType.': '.round(($time_end - $time_start), 3)."\n";
}
Résultats:
Commentaires:
Du côté de MySQL, pas trop de différences entre les tables MyISAM et InnoDB. Je sais que MyISAM ne supporte pas les transactions mais j'ai fait le test sans BEGIN ... COMMIT et ça ne change rien au résultat. Sans doute que le pilote PDO_MYSQL se charge lui même de désactiver les transactions pour les tables MyISAM (merci PDO!).
En première analyse SQLite s'en sort mieux que les autres. Reste à voir comment elle se comporte en INSERT concurrents. La gestion d'accès concurrents de SQLite
ne semble pas être son point fort. Mon test d'accès concurrents consiste à lancer trois processus concurrents en console (avec l'utisisation de &). Chaque processus fait 10.000 INSERT, et puis là, surprise, SQLite3 semble tenir mieux la charge que les autres:
Pas mal pour SQLite que je voyais jusqu'ici comme une solution pour des sites à faible fréquentation mais je vais peut-être changer d'avis sur la question. Je lui vois bien des avantages: totalement libre (domaine public) ,très léger, pas de serveur (fichier "plat"), portable etc... En tout cas, toutes mes nouvelles appli sont en PDO, on ne sait jamais que l'envie me prenne de changer de SGBD. Toutes mes requêtes SQL sont testées sous MySQL et SQLite3 au cas ou...
Par contre, Postgres se traîne dans ce test. Je ne connais pas bien ce SGBD et ai fait confiance au pilote PDO pour optimiser les INSERTs.
Si vous avez d'autres idées de test.... Je reviens bientôt avec les résultats de test de SELECT sur une grosse table (plus d'un million de lignes).
Bonjour,
Je suis en cours de test comparatif pour les trois SGBD en sujet. Ce test n'a absolument pas de valeur scientifique. Juste un petit test empirique pour démystifier les lieux communs. Vous pouvez vous même faire ce test avec le code donné plus bas.
Je viens de terminer la première phase: insertion de données. Le reste suivra au fur et à mesure.
[b]Méthodologie:[/b]
[list][*]Utilisation de la classe d'abstraction PDO (encore heureux qu'elle existe!)
[*]Utilisation des "prepared statement" c'est à dire la compilation côté serveur d'une requête répétitive
[*]Utilisation des transactions si elles sont supportées (BEGIN ... COMMIT)
[*]Insertion de 10.000 chaînes aléatoires sur 4 colonnes.
[*]Test d'insertions concurrentes en lançant des processus d'insertion concurrents
[*]Serveur de test: hors charge, Pentium 4 2.4 Ghz - 768 MB ram - Linux Debian.
[*]PHP 5.2 (avec extension PDO), Mysql 5.0, SQLite 3.3, Postgres 8.2[/list]
[b]Code du test:[/b]
[php]/* production des chaînes aléatoires à insérer */
for ($i = 0; $i < 10000; $i++){
$aCol1[$i] = md5(mt_rand(1, 5000));
$aCol2[$i] = md5(mt_rand(1, 5000));
$aCol3[$i] = md5(mt_rand(1, 5000));
$aCol4[$i] = md5(mt_rand(1, 5000));
}
/* Paramètres des bdd et types de tables*/
$aDbs = array(
'SQLite' => '',
'Postgr' => '',
'MyISAM' => 'ENGINE=MyISAM',
'InnoDB' => 'ENGINE=InnoDB',
);
foreach ($aDbs as $dbType => $engine){
/* Connexion PDO aux bdd */
if ($dbType == 'SQLite'){
$pdo = new PDO('sqlite:/var/lib/sqlite/test.sqlite3');
} elseif ($dbType == 'Postgr'){
$pdo = new PDO('pgsql:host=localhost dbname=test user=****** password=********');
} else {
$pdo = new PDO('mysql:dbname=test;host=localhost', '****', '*******');
}
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
/* RAZ et création d'une table */
$qry = 'DROP TABLE IF EXISTS table1';
$pdo->exec($qry);
$qry = 'CREATE TABLE table1 ( col1 VARCHAR(50), col2 VARCHAR(50), col3 VARCHAR(50), col4 VARCHAR(50)) '.$engine;
$pdo->exec($qry);
/* Insertion: préparation et exécution */
$time_start = microtime(true);
$insert = "INSERT INTO table1 (col1, col2, col3, col4) VALUES (:val1, :val2, :val3, :val4)";
$result = $pdo->prepare($insert);
$pdo->beginTransaction();
foreach ($aCol1 as $k => $v){
$result->execute(array(':val1' => $aCol1[$k], ':val2' => $aCol2[$k], ':val3' => $aCol3[$k], ':val4' => $aCol2[$k]));
}
$pdo->commit();
$time_end = microtime(true);
echo $dbType.': '.round(($time_end - $time_start), 3)."\n";
}[/php]
[b]Résultats:[/b]
[code]SQLite: 0.385
Postgr: 4.369
MyISAM: 1.128
InnoDB: 1.171
[/code]
[b]Commentaires:[/b]
Du côté de MySQL, pas trop de différences entre les tables MyISAM et InnoDB. Je sais que MyISAM ne supporte pas les transactions mais j'ai fait le test sans BEGIN ... COMMIT et ça ne change rien au résultat. Sans doute que le pilote PDO_MYSQL se charge lui même de désactiver les transactions pour les tables MyISAM (merci PDO!).
En première analyse SQLite s'en sort mieux que les autres. Reste à voir comment elle se comporte en INSERT concurrents. La gestion d'accès concurrents de SQLite [url=http://www.sqlite.org/faq.html#q5]ne semble pas être son point fort[/url]. Mon test d'accès concurrents consiste à lancer trois processus concurrents en console (avec l'utisisation de &). Chaque processus fait 10.000 INSERT, et puis là, surprise, SQLite3 semble tenir mieux la charge que les autres:
[code]SQLite: 1.984
Postgr: 29.205
MyISAM: 8.312
InnoDB: 9.176
[/code]
Pas mal pour SQLite que je voyais jusqu'ici comme une solution pour des sites à faible fréquentation mais je vais peut-être changer d'avis sur la question. Je lui vois bien des avantages: totalement libre (domaine public) ,très léger, pas de serveur (fichier "plat"), portable etc... En tout cas, toutes mes nouvelles appli sont en PDO, on ne sait jamais que l'envie me prenne de changer de SGBD. Toutes mes requêtes SQL sont testées sous MySQL et SQLite3 au cas ou...
Par contre, Postgres se traîne dans ce test. Je ne connais pas bien ce SGBD et ai fait confiance au pilote PDO pour optimiser les INSERTs.
Si vous avez d'autres idées de test.... Je reviens bientôt avec les résultats de test de SELECT sur une grosse table (plus d'un million de lignes).