Les moteurs de stockage de MySQL
4 Octobre 2008 00:46 | Par Miss Lemon dans Développement

Me voilà en train de créer une base de données sur MySQL via PhpMyAdmin (histoire de pas me casser la tête).
Mais voilà je reste perplexe devant le choix de la liste déroulante "Moteur de Stockage". Habituellement, je ne me pose pas de question est laisse le choix par défaut, c'est à dire MyISAM, et puis voilà . Mais , si plusieurs types existent, il doit y avoir un intérêt, et là , j'ai eu envie de creuser un peu le sujet (et donc de me casser un peu la tête :) ).
Bien choisir son moteur fait partie du processus d'optimisation d'une base de données.
Voici donc un petit tour d'horizon des différents moteurs, et quelques tests comparatifs pour en savoir plus.
Les différents types
Tout d'abord sous MySQL on a deux types distincts, un moteur pour:
- les tables transactionnelles (TST)
- les tables non transactionnelles (NTST)
Avantages de chaque types
TST
- Plus sûr. Permet de recouvrer ses données en cas de crash
- Permet de combiner plusieurs commandes et de les accepter d'un coup à l'aide de COMMIT
- Hors mode AUTO COMMIT permet d'annuler les modifications à l'aide de ROLLBACK
- Si une mise à jour échoue, tous les chargements sont annulés
- Plus rapides. Pas de traitements des transactions
- Moins gourmande en espace disque. Pas de traitements des transactions
- Moins gourmande en mémoire pour les mises à jour
Les différents moteurs
Pour faire simple, je vais me pencher uniquement sur les types mis à ma disposition sur la version que j'utilise, c'est à dire Mysql 5.0, pour un PHPMyAdmin 2.11.
- MyISAM
- Memory (Heap)
- InnoDB
- Blackhole
- Archive
- CSV
- Federated
- MRG_MyISAM
MyISAM
C'est le moteur par défaut de MySQL. C'est le successeur du moteur ISAM voué à disparaitre.
C'est le plus simple à utiliser et à mettre en œuvre.
Il utilise plusieurs fichiers qui grandissent au fur et à mesure que la base grossit.
Il ne supporte ni les transactions, ni les clefs étrangères.
MyISAM utilise un mécanisme de verrouillage des tables pour optimiser plusieurs opérations de lecture et d'écriture simultanées. En échange, il faut exécuter la commande OPTIMIZE TABLE de temps en temps pour récupérer l'espace occupé inutilement.
Il prend en charge les index FULLTEXT.
Memory (Heap)
Ce moteur stockent les tables uniquement en mémoire.
La structure de la base est stockée sur le disque dur mais les données sont stockées dans la RAM, donc si la machine serveur redémarre, les données seront perdues.
Cependant, étant donné qu'il n'y a plus d'accès disque, une requête de modification (UPDATE, INSERT, ...) s'exécutera sensiblement plus rapidement.
InnoDB
Ce moteur a été créé et est maintenu par InnoBase (racheté par Oracle en 2005).
Il gère les transactions et les clefs étrangères (et donc une gestion d'intégrité de table).
En contrepartie, les bases qui l'utilisent occupent bien plus d'espace sur le disque.
Blackhole
Ce moteur réceptionne les données, les transfère mais ne les stocke pas.
(Ce type de base ne fera pas partie de mes tests comparatifs)
Archive
Ce moteur est adapté à l'archivage de données.
Les lignes sont compressées au fur et à mesure de leur insertion.
Les requêtes de recherches sont alors sensiblement plus lentes.
CSV
Ce moteur utilise des fichiers textes (au format CSV) comme stockage.
Federated
Ce moteur permet d'accéder à des tables d'une base de données distantes plutôt que dans les fichiers locaux.
(Ce type de base ne fera pas partie de mes tests comparatifs)
MRG_MyISAM ou MERGE
Ce moteur est fait pour fusionner plusieurs tables qui doivent être identiques.
(Ce type de base ne fera pas partie de mes tests comparatifs)
Comparatif des moteurs
Pour faire des tests, je crée des tables de même structure dont la seule différence sera le moteur.
Petites infos tout de même:
Voici le script de création de la table, avec #### à remplacer par le nom du moteur parmi la liste suivante: myisam, innodb, archive, csv et memory.
La comparaison se fait sur :
Le contenu est identique dans chaque table.
La requête d'insertion est la suivante (avec $i allant de 1 à 99999):
On constate que la taille de table_csv est de zéro octets. Logique, puisque les données sont stockées en fichiers csv.
Au final, la table memory ne comporte que 21580 lignes. Je suppose que la taille mémoire permise a été atteinte, mais sur ce point si quelqu'un sait pourquoi, je veux bien la réponse.
On peut aussi regarder directement la taille des fichiers sur le disque.
Dans le dossier /var/lib/mysql/nom_de_ma_base/, on trouve des fichiers table_####.***
Les extensions de fichiers existantes sont les suivantes:
Pour le stockage des tables csv, comme les données sont stockées sur des fichiers, il est logique que l'on retrouve ici le véritable espace utilisé.
Pour le stockage des tables memory, comme les données sont stockées en mémoire, il est logique de retrouver un tout petit 12K d'espace occupé sur le disque.
Pour le stockage des tables InnoDB, il faut rergarder un autre fichier, nommé ibdata1
Deuxième comparaison: le temps de réponse (sur les tables remplies)
Requête 1: SELECT COUNT(*) FROM table_####;
Requête 2: SELECT id FROM table_#### WHERE description LIKE '%5%';
Requête 3: UPDATE table_#### SET description = 'new description' WHERE description LIKE '%5%';
Conclusion
Les tables qui stockent en mémoire (MEMORY) sont sensiblement plus rapide, mais c'est évidement volatile.
Les tables qui stockent dans des fichiers (CSV) donnent des temps de traitement bien plus longs, par contre vous retrouvez toutes vos données en CSV, ce qui peut , peut être , être utile pour des export de données.
Pour un projet web, le véritable choix doit se faire entre InnoDB et MyISAM.
InnoDB prend plus de place, est plus lent. Alors quel serait l'avantage de prendre InnoDB plutôt qur MyISAM puisque les tests ci dessus ne lui donnent pas d'avantages.
Et bien, c'est le fait qu'il soit TRANSACTIONNELS (BEGIN, COMMIT, ROLLBACK) et qu'il puisse gérer les clés étrangères (FOREIGN KEY).
Admettons 2 tables, une table AUTEUR et une table LIVRE, créés en InnoDB.
Dans le cas de tables MyISAM, pour supprimer un auteur et tous les livres qui lui sont associés, il faudra faire la requête sur la table LIVRE PUIS sur la table AUTEUR.
Dans le cas de tables InnoDB, une seule requête sur la table AUTEUR suffira à tout supprimer.
Source:
Wikipedia
Zdnet.fr
Developpez.com
Browardphp.com
Le PHP facile
MySQL Performance Blog
Apprendre-php.com
Tux-Planet
PHP Team
C'est le moteur par défaut de MySQL. C'est le successeur du moteur ISAM voué à disparaitre.
C'est le plus simple à utiliser et à mettre en œuvre.
Il utilise plusieurs fichiers qui grandissent au fur et à mesure que la base grossit.
Il ne supporte ni les transactions, ni les clefs étrangères.
MyISAM utilise un mécanisme de verrouillage des tables pour optimiser plusieurs opérations de lecture et d'écriture simultanées. En échange, il faut exécuter la commande OPTIMIZE TABLE de temps en temps pour récupérer l'espace occupé inutilement.
Il prend en charge les index FULLTEXT.
Memory (Heap)
Ce moteur stockent les tables uniquement en mémoire.
La structure de la base est stockée sur le disque dur mais les données sont stockées dans la RAM, donc si la machine serveur redémarre, les données seront perdues.
Cependant, étant donné qu'il n'y a plus d'accès disque, une requête de modification (UPDATE, INSERT, ...) s'exécutera sensiblement plus rapidement.
InnoDB
Ce moteur a été créé et est maintenu par InnoBase (racheté par Oracle en 2005).
Il gère les transactions et les clefs étrangères (et donc une gestion d'intégrité de table).
En contrepartie, les bases qui l'utilisent occupent bien plus d'espace sur le disque.
Blackhole
Ce moteur réceptionne les données, les transfère mais ne les stocke pas.
(Ce type de base ne fera pas partie de mes tests comparatifs)
Archive
Ce moteur est adapté à l'archivage de données.
Les lignes sont compressées au fur et à mesure de leur insertion.
Les requêtes de recherches sont alors sensiblement plus lentes.
CSV
Ce moteur utilise des fichiers textes (au format CSV) comme stockage.
Federated
Ce moteur permet d'accéder à des tables d'une base de données distantes plutôt que dans les fichiers locaux.
(Ce type de base ne fera pas partie de mes tests comparatifs)
MRG_MyISAM ou MERGE
Ce moteur est fait pour fusionner plusieurs tables qui doivent être identiques.
(Ce type de base ne fera pas partie de mes tests comparatifs)
Comparatif des moteurs
Pour faire des tests, je crée des tables de même structure dont la seule différence sera le moteur.
Petites infos tout de même:
- Le type MEMORY ne supporte pas les champs de type BLOB/TEXT, je ferais donc un champ de type VARCHAR(255).
- Les types ARCHIVES et CSV ne supportent pas l'auto-increment, ni les clés , par conséquent pas de champ auto-incrémenté ou de clé primaire sur ces tables de test
- Le type FEDERATED necessite un commentaire de table précisant le serveur distant auquel cotre serveur client va se connecter .
Ce commentaire doit être du type "scheme://user_name[:password]@host_name[:port_num]:/db_name/tbl_name", mais comme je le précisais ci dessus, je ne ferais pas de test sur ce type de base.
Voici le script de création de la table, avec #### à remplacer par le nom du moteur parmi la liste suivante: myisam, innodb, archive, csv et memory.
CREATE TABLE `table_####` ( `id` INT( 6 ) NULL , `description` TEXT NULL , `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE =####Première comparaison: la taille des tables
La comparaison se fait sur :
- les tables vides
- les tables avec un peu de données (1000 lignes)
- les tables avec beaucoup de données (99999 lignes)
Le contenu est identique dans chaque table.
La requête d'insertion est la suivante (avec $i allant de 1 à 99999):
INSERT INTO table_#### (id, description) VALUES ($i, 'champ texte $i auto rempli histoire de voir un peu ce que ça donne ');Pour connaitre la taille (en octet) des tables, en mode console, vous avez l'instruction suivante:
misslemon:~# mysql -h localhost -u login -p -e "SHOW TABLE STATUS FROM database_name LIKE 'table_name'\G" | grep Data_length Enter password:
| Nom de la table | table vide | 1000 lignes | 99999 lignes |
| table_archive | 22 | 8732 (~8Ko) | 811548 (~792Ko) |
| table_csv | 0 | 0 | 0 |
| table_innodb | 16384 (16Ko) | 147456 (144Ko) | 12075008 (~11Mo) |
| table_memory | 0 | 909432 (~888Ko) | 16898960 (~16Mo) |
| table_myisam | 0 | 87604 (~85Ko) | 8799516 (~8Mo) |
On constate que la taille de table_csv est de zéro octets. Logique, puisque les données sont stockées en fichiers csv.
Au final, la table memory ne comporte que 21580 lignes. Je suppose que la taille mémoire permise a été atteinte, mais sur ce point si quelqu'un sait pourquoi, je veux bien la réponse.
On peut aussi regarder directement la taille des fichiers sur le disque.
du -sh /var/lib/mysql/nom_de_ma_base/La base fait : 18M
Dans le dossier /var/lib/mysql/nom_de_ma_base/, on trouve des fichiers table_####.***
Les extensions de fichiers existantes sont les suivantes:
- .frm: Ces fichiers stockent les définitions de table pour tous les types de tables
- .MYD et .MYI: Ce sont les fichiers de données (MYD = MYData) et les fichiers d'indexs (MYI = MYIndex) pour les tables MyIsam
- .ARM et .ARZ: pour les tables archive
- .CSV: pour les tables csv
ls /var/lib/mysql/nom_de_ma_base/table_####.* | xargs du -csh
| Nom de la table | 99999 lignes |
| table_archive | 820K |
| table_csv | 8,2M |
| table_innodb | 12K |
| table_memory | 12K |
| table_myisam | 8,5M |
Pour le stockage des tables csv, comme les données sont stockées sur des fichiers, il est logique que l'on retrouve ici le véritable espace utilisé.
Pour le stockage des tables memory, comme les données sont stockées en mémoire, il est logique de retrouver un tout petit 12K d'espace occupé sur le disque.
Pour le stockage des tables InnoDB, il faut rergarder un autre fichier, nommé ibdata1
du -sh /var/lib/mysql/ibdata1J'obtiens cette fois 27Mo, plus logique que les 12Ko trouvés ci dessus.
Deuxième comparaison: le temps de réponse (sur les tables remplies)
Requête 1: SELECT COUNT(*) FROM table_####;
Requête 2: SELECT id FROM table_#### WHERE description LIKE '%5%';
Requête 3: UPDATE table_#### SET description = 'new description' WHERE description LIKE '%5%';
| Nom de la table | Requête 1 | Requête 2 | Requête 3 |
| table_archive | 1 row in set (0.52 sec) | 40951 rows in set (0.99 sec) | Table storage engine for 'table_archive' doesn't have this option => plantage mysql |
| table_csv | 1 row in set (0.70 sec) | 40951 rows in set (1.17 sec) | Query OK, 40951 rows affected (5 min 4.24 sec) |
| table_innodb | 1 row in set (0.43 sec) | 40951 rows in set (0.92 sec) | Query OK, 40951 rows affected (9.12 sec) |
| table_memory | 1 row in set (0.00 sec) | 7325 rows in set (0.16 sec) | Query OK, 0 rows affected (0.00 sec |
| table_myisam | 1 row in set (0.00 sec) | 40951 rows in set (0.59 sec) | Query OK, 40951 rows affected (3.45 sec) |
Conclusion
Les tables qui stockent en mémoire (MEMORY) sont sensiblement plus rapide, mais c'est évidement volatile.
Les tables qui stockent dans des fichiers (CSV) donnent des temps de traitement bien plus longs, par contre vous retrouvez toutes vos données en CSV, ce qui peut , peut être , être utile pour des export de données.
Pour un projet web, le véritable choix doit se faire entre InnoDB et MyISAM.
InnoDB prend plus de place, est plus lent. Alors quel serait l'avantage de prendre InnoDB plutôt qur MyISAM puisque les tests ci dessus ne lui donnent pas d'avantages.
Et bien, c'est le fait qu'il soit TRANSACTIONNELS (BEGIN, COMMIT, ROLLBACK) et qu'il puisse gérer les clés étrangères (FOREIGN KEY).
Admettons 2 tables, une table AUTEUR et une table LIVRE, créés en InnoDB.
CREATE TABLE auteur (
id_auteur tinyint(2) NOT NULL AUTO_INCREMENT,
nom_auteur varchar(20) NOT NULL DEFAULT ''
PRIMARY KEY (id_auteur)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE livre(
id_livre tinyint( 2 ) NOT NULL AUTO_INCREMENT ,
titre_livre varchar( 40 ) NOT NULL DEFAULT '',
id_auteur tinyint( 2 ) NOT NULL,
PRIMARY KEY ( id_livre ) ,
FOREIGN KEY (id_auteur) REFERENCES auteur(id_auteur) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = latin1 AUTO_INCREMENT =1 ;
Dans le cas de tables MyISAM, pour supprimer un auteur et tous les livres qui lui sont associés, il faudra faire la requête sur la table LIVRE PUIS sur la table AUTEUR.
Dans le cas de tables InnoDB, une seule requête sur la table AUTEUR suffira à tout supprimer.
Source:
Wikipedia
Zdnet.fr
Developpez.com
Browardphp.com
Le PHP facile
MySQL Performance Blog
Apprendre-php.com
Tux-Planet
PHP Team







Commentaires
Aucun commentaire pour le moment.
Ajouter un commentaire