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
/* 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:
Code : Tout sélectionner
SQLite: 0.385
Postgr: 4.369
MyISAM: 1.128
InnoDB: 1.171
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:
Code : Tout sélectionner
SQLite: 1.984
Postgr: 29.205
MyISAM: 8.312
InnoDB: 9.176
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).