MyISAM contre InnoDB [fermé]

857

Je travaille sur un projet qui implique beaucoup d'écritures de bases de données, je dirais ( 70% d'inserts et 30% de lectures ). Ce ratio comprendrait également les mises à jour que je considère comme une lecture et une écriture. Les lectures peuvent être sales (par exemple, je n'ai pas besoin d'informations précises à 100% au moment de la lecture).
La tâche en question fera plus d'un million de transactions de base de données par heure.

J'ai lu un tas de trucs sur le Web sur les différences entre MyISAM et InnoDB, et MyISAM semble être le choix évident pour moi pour la base de données / tables particulières que j'utiliserai pour cette tâche. D'après ce que je semble lire, InnoDB est bon si des transactions sont nécessaires car le verrouillage au niveau des lignes est pris en charge.

Quelqu'un at-il une expérience avec ce type de charge (ou plus)? MyISAM est-il la voie à suivre?

user2013
la source
13
Le blog sur les performances MySQL est une excellente ressource pour ce type de chose.
ceejayoz
3
Cela dépendra un peu de si votre système est OLTP ou plus orienté datawarehouse (où la plupart des écritures sont des chargements en masse).
nos
35
MyISAM ne prend pas en charge le verrouillage de ligne, les transactions, il ne prend même pas en charge les clés étrangères ... diable, car il ne peut pas fournir ACID , il peut même difficilement être considéré comme une base de données appropriée! C'est pourquoi InnoDB est le moteur par défaut depuis MySQL 5.5 ... mais, pour une raison quelconque, MyISAM continue d'être le moteur par défaut pour les tables créées dans PhpMyAdmin, donc beaucoup de bases de données amateurs depuis tournées sur MyISAM.
BlueRaja - Danny Pflughoeft
Voir tous les moteurs MySql DB comparés
Somnath Muluk

Réponses:

523

J'ai brièvement discuté de cette question dans un tableau afin que vous puissiez conclure si vous allez avec InnoDB ou MyISAM .

Voici un petit aperçu du moteur de stockage db que vous devez utiliser dans quelle situation:

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
Recherche de texte intégral requise Oui 5.6.4
-------------------------------------------------- --------------
Exiger des transactions Oui
-------------------------------------------------- --------------
Requêtes de sélection fréquentes Oui      
-------------------------------------------------- --------------
Insertion, mise à jour, suppression fréquentes Oui
-------------------------------------------------- --------------
Verrouillage des lignes (multi-traitement sur une seule table) Oui
-------------------------------------------------- --------------
Conception de base relationnelle Oui

Sommaire

  • Dans presque toutes les circonstances, InnoDB est la meilleure solution
  • Mais, lecture fréquente, presque pas d'écriture, utilisez MyISAM
  • Recherche plein texte dans MySQL <= 5.5, utilisez MyISAM
développeur99
la source
11
InnoDB a des index de texte intégral dans MySQL 5.6, mais jusqu'à présent, ils ne sont pas vraiment prêts pour une utilisation en production.
Bill Karwin
3
Conformément à 12.9. Fonctions de recherche de texte intégral, "Les index de texte intégral ne peuvent être utilisés qu'avec les tables InnoDB ou MyISAM". Semble OK pour MySQL> = 5.6, mais la même page pour MySQL 5.5, dit toujours "Les index de texte intégral ne peuvent être utilisés qu'avec les tables MyISAM". Le tableau ci-dessus pourrait être mis à jour pour indiquer en quoi il diffère des versions de MySQL. Malheureusement, jusqu'à présent, MySQL 5.5 semble être la norme.
Hibou57
2
Que signifie: InnoDB - full-text: 5.6.4?? C'est oui ou non?
2
MyISAM stocke également le nombre de lignes en interne. Par conséquent, la fonction Count () est presque gratuite dans MyISAM, alors qu'elle prend un temps considérable dans InnoDB.
Hedeshy
3
bonne table, mais en ajoutant une ligne pour la qualité et la stabilité, MyIsam = no, innoDB = yes le rendrait encore meilleur
pilavdzice
268

Je ne suis pas un expert en bases de données et je ne parle pas d'expérience. Toutefois:

Les tables MyISAM utilisent le verrouillage au niveau de la table . Sur la base de vos estimations de trafic, vous avez près de 200 écritures par seconde. Avec MyISAM, un seul d'entre eux pourrait être en cours à tout moment . Vous devez vous assurer que votre matériel peut suivre ces transactions pour éviter d'être dépassé, c'est-à-dire qu'une seule requête ne peut pas prendre plus de 5 ms.

Cela me suggère que vous auriez besoin d'un moteur de stockage qui prend en charge le verrouillage au niveau des lignes, c'est-à-dire InnoDB.

En revanche, il devrait être assez trivial d'écrire quelques scripts simples pour simuler la charge avec chaque moteur de stockage, puis comparer les résultats.

rix0rrr
la source
12
Près de 200? Si sa transaction moyenne fait 2,5 requêtes, c'est [(2,5 * 1M) / 3600s =] plus proche de 700.
Ozzy
12
Je suis également en désaccord avec a single query can take no more than 5msvous parce que vous avez fait 2 hypothèses peu probables; R: toutes les requêtes avaient besoin de la même table & B: il n'y avait qu'une seule connexion disponible! Je dois vous informer qu'une configuration Linux & MySQL 5.5 avec une RAM élevée peut prendre en charge jusqu'à 10 000 connexions simultanées (Voir: dev.mysql.com/doc/refman//5.5/en/too-many-connections.html )
Ozzy
152
Lorsqu'une table est verrouillée, une seule requête peut s'exécuter à la fois. Peu importe si le serveur prend en charge 10000 connexions simultanées, chacune sauvegardera pendant que la table est verrouillée.
Ryaner
2
Il peut également être utile de savoir que MyISAM prend en charge l'index spatial, contrairement à InnoDB. Et MyISAM ne semble pas utiliser de clés étrangères même si cela n'empêche pas d'en créer une.
kriver
4
@kriver: Vous ne pouvez pas avoir de clés étrangères dans les tables MyISAM. Vous pouvez inclure des définitions FK dans les instructions CREATE TABLE mais elles (les définitions) sont simplement ignorées.
ypercubeᵀᴹ
191

Les gens parlent souvent de performances, de lectures et d'écritures, de clés étrangères, etc. mais il y a une autre fonctionnalité indispensable pour un moteur de stockage à mon avis: les mises à jour atomiques.

Essaye ça:

  1. Émettez une MISE À JOUR par rapport à votre table MyISAM qui prend 5 secondes.
  2. Pendant la mise à jour, disons 2,5 secondes, appuyez sur Ctrl-C pour l'interrompre.
  3. Observez les effets sur la table. Combien de lignes ont été mises à jour? Combien n'ont pas été mis à jour? Le tableau est-il même lisible, ou était-il corrompu lorsque vous appuyez sur Ctrl-C?
  4. Essayez la même expérience avec UPDATE sur une table InnoDB, interrompant la requête en cours.
  5. Observez le tableau InnoDB. Zéro lignes ont été mises à jour. InnoDB a assuré que vous disposiez de mises à jour atomiques, et si la mise à jour complète n'a pas pu être validée, elle annule la totalité du changement. En outre, la table n'est pas corrompue. Cela fonctionne même si vous utilisez killall -9 mysqldpour simuler un crash.

Les performances sont certes souhaitables, mais ne pas perdre de données devrait l'emporter sur cela.

Bill Karwin
la source
4
Pour mémoire, les autres caractéristiques d'une base de données ACID - Cohérence, Isolation et Durabilité - ne sont pas non plus prises en charge par MyISAM.
Bill Karwin
Control-C ne doit pas corrompre la table - comme dans CHECK TABLE renverra le succès et toutes les requêtes se poursuivront sans erreurs. MyISAM abandonnera la mise à jour sans mettre à jour tous les enregistrements, mais la table conservera l'intégrité structurelle interne. Tuer mysqld avec SIGTERM aura le même effet. Cependant, si vous lui donnez SIGKILL (kill -9) ou un signal de plantage (ou s'il le gagne tout seul quand il rencontre un bug), ou si le système d'exploitation tombe en panne / l'alimentation est perdue, alors c'est une autre histoire - vous pouvez voir Corruption au niveau de MyISAM.
Sasha Pachev,
1
InnoDB peut également se corrompre royalement, généralement plus royalement que MyISAM quand il le fait. L'ironie de l'ACID est que nous avons la notion de tout ou rien. Donc, quand InnoDB ne peut pas tout donner, il ne donne rien - assertion interne, et il refuse de s'exécuter du tout parce qu'un octet dans une structure est incorrecte - 90% du temps, il aurait pu être ignoré et cela n'affecterait tout au plus qu'une seule table. Les serveurs Percona récents ont la possibilité de s'en occuper - innodb_pass_corrupt_table.
Sasha Pachev,
1
Je cherchais ce genre d'informations depuis 3 jours, maintenant je l'ai. InnoDB est le meilleur. MerciBill Karwin
user3833682
3
@ flow2k, presque aucun, de nos jours. Lors de mon dernier travail, nous avons utilisé MyISAM pour une table sur un serveur, et la seule raison était que MyISAM était capable de stocker cette table spécifique dans moins d'espace qu'InnoDB n'en aurait. Nous étions limités sur l'espace disque, nous avons donc dû utiliser MyISAM jusqu'à ce que nous puissions déplacer la base de données vers un autre serveur. Lors de mon nouvel emploi, il existe déjà une politique selon laquelle chaque table doit être InnoDB.
Bill Karwin
138

J'ai travaillé sur un système à haut volume utilisant MySQL et j'ai essayé MyISAM et InnoDB.

J'ai constaté que le verrouillage au niveau de la table dans MyISAM a provoqué de graves problèmes de performances pour notre charge de travail, ce qui ressemble au vôtre. Malheureusement, j'ai également constaté que les performances sous InnoDB étaient également pires que ce que j'avais espéré.

En fin de compte, j'ai résolu le problème de contention en fragmentant les données de telle sorte que les insertions sont entrées dans une table "chaude" et que les sélections n'ont jamais interrogé la table chaude.

Cela a également permis à des suppressions (les données étaient sensibles au temps et nous ne conservions que X jours) de se produire sur des tables "périmées" qui, encore une fois, n'étaient pas touchées par certaines requêtes. InnoDB semble avoir de mauvaises performances sur les suppressions en masse, donc si vous prévoyez de purger les données, vous voudrez peut-être les structurer de telle manière que les anciennes données se trouvent dans une table périmée qui peut simplement être supprimée au lieu d'exécuter des suppressions.

Bien sûr, je n'ai aucune idée de votre application, mais j'espère que cela vous donnera un aperçu de certains des problèmes avec MyISAM et InnoDB.

alanc10n
la source
3
"En fin de compte, j'ai résolu le problème de contention en fragmentant les données de telle sorte que les insertions sont entrées dans une table" chaude "et que les sélections n'ont jamais interrogé la table chaude."
N'est-
15
Danny - Non, pas vraiment. Le réglage des paramètres du serveur est important, mais ne remplace en aucun cas une structuration réfléchie de votre schéma. Si vous avez une base de données beaucoup, beaucoup plus grande que la RAM disponible et des modèles d'accès qui touchent les données de manière aléatoire tout au long de la base de données, alors tout le réglage du pool de tampons dans le monde ne vous aidera pas. Si vous comprenez les données et les modèles d'accès, vous pouvez atténuer une grande partie de la douleur grâce à une conception soignée.
alanc10n
66

Un peu tard dans le jeu ... mais voici un article assez complet que j'ai écrit il y a quelques mois , détaillant les principales différences entre MYISAM et InnoDB. Prenez une tasse de thé (et peut-être un biscuit) et dégustez.


La principale différence entre MyISAM et InnoDB réside dans l'intégrité référentielle et les transactions. Il existe également d'autres différences telles que le verrouillage, les restaurations et les recherches de texte intégral.

Intégrité référentielle

L'intégrité référentielle garantit que les relations entre les tables restent cohérentes. Plus précisément, cela signifie que lorsqu'une table (par exemple, les listes) a une clé étrangère (par exemple, l'ID de produit) pointant vers une table différente (par exemple, les produits), lorsque des mises à jour ou des suppressions se produisent dans la table pointée, ces modifications sont répercutées en cascade sur la liaison table. Dans notre exemple, si un produit est renommé, les clés étrangères de la table de liaison seront également mises à jour; si un produit est supprimé du tableau «Produits», toutes les listes qui pointent vers l'entrée supprimée seront également supprimées. En outre, toute nouvelle liste doit avoir cette clé étrangère pointant vers une entrée existante valide.

InnoDB est un SGBD relationnel (RDBMS) et a donc une intégrité référentielle, contrairement à MyISAM.

Transactions et atomicité

Les données d'une table sont gérées à l'aide d'instructions DML (Data Manipulation Language), telles que SELECT, INSERT, UPDATE et DELETE. Une transaction regroupe deux instructions DML ou plus en une seule unité d'oeuvre, de sorte que l'unité entière est appliquée, ou aucune d'elles.

MyISAM ne prend pas en charge les transactions, contrairement à InnoDB.

Si une opération est interrompue lors de l'utilisation d'une table MyISAM, l'opération est immédiatement abandonnée et les lignes (ou même les données de chaque ligne) qui sont affectées restent affectées, même si l'opération ne s'est pas terminée.

Si une opération est interrompue lors de l'utilisation d'une table InnoDB, parce qu'elle utilise des transactions, qui ont l'atomicité, toute transaction qui ne s'est pas terminée ne prendra pas effet, car aucune validation n'est effectuée.

Verrouillage de table vs verrouillage de ligne

Lorsqu'une requête s'exécute sur une table MyISAM, la table entière dans laquelle elle interroge sera verrouillée. Cela signifie que les requêtes suivantes ne seront exécutées qu'après la fin de la requête en cours. Si vous lisez une grande table et / ou si les opérations de lecture et d'écriture sont fréquentes, cela peut signifier un énorme arriéré de requêtes.

Lorsqu'une requête s'exécute sur une table InnoDB, seules les lignes impliquées sont verrouillées, le reste de la table reste disponible pour les opérations CRUD. Cela signifie que les requêtes peuvent s'exécuter simultanément sur la même table, à condition qu'elles n'utilisent pas la même ligne.

Cette fonctionnalité dans InnoDB est connue sous le nom de simultanéité. Aussi grande que soit la concurrence, il existe un inconvénient majeur qui s'applique à une plage sélectionnée de tables, en ce sens qu'il y a un surcoût lors du basculement entre les threads du noyau, et vous devez définir une limite sur les threads du noyau pour empêcher le serveur de s'arrêter .

Transactions et annulations

Lorsque vous exécutez une opération dans MyISAM, les modifications sont définies; dans InnoDB, ces modifications peuvent être annulées. Les commandes les plus courantes utilisées pour contrôler les transactions sont COMMIT, ROLLBACK et SAVEPOINT. 1. COMMIT - vous pouvez écrire plusieurs opérations DML, mais les modifications ne seront enregistrées que lorsqu'un COMMIT est effectué 2. ROLLBACK - vous pouvez ignorer toutes les opérations qui n'ont pas encore été validées 3. SAVEPOINT - définit un point dans la liste des opérations auxquelles une opération ROLLBACK peut revenir en arrière

Fiabilité

MyISAM n'offre aucune intégrité des données - Les pannes matérielles, les arrêts impurs et les opérations annulées peuvent entraîner la corruption des données. Cela nécessiterait une réparation complète ou des reconstructions des index et des tables.

InnoDB, d'autre part, utilise un journal des transactions, un tampon de double écriture et une somme de contrôle et une validation automatiques pour éviter la corruption. Avant qu'InnoDB n'apporte de modifications, il enregistre les données avant les transactions dans un fichier d'espace disque logique système appelé ibdata1. En cas de plantage, InnoDB récupère automatiquement via la relecture de ces journaux.

Indexation FULLTEXT

InnoDB ne prend pas en charge l'indexation FULLTEXT jusqu'à MySQL version 5.6.4. Au moment de la rédaction de cet article, la version MySQL de nombreux hébergeurs partagés est toujours inférieure à 5.6.4, ce qui signifie que l'indexation FULLTEXT n'est pas prise en charge pour les tables InnoDB.

Cependant, ce n'est pas une raison valable pour utiliser MyISAM. Il est préférable de passer à un fournisseur d'hébergement qui prend en charge les versions à jour de MySQL. Ce n'est pas qu'une table MyISAM qui utilise l'indexation FULLTEXT ne peut pas être convertie en table InnoDB.

Conclusion

En conclusion, InnoDB devrait être votre moteur de stockage par défaut de choix. Choisissez MyISAM ou d'autres types de données lorsqu'ils répondent à un besoin spécifique.

d4nyll
la source
Je faisais un script de somme de contrôle de session php et la plupart de mes clés sont des chaînes aléatoires de [az09] ... Innodb a pris plus de 30 ms pour le faire INSERT ON DUPLICATE KEY UPDATE, j'ai donc essayé MyISAM et maintenant c'est <1 ms ... Beaucoup de réponses que j'ai vues disent que innodb a du mal à gérer les clés uniques «non triables» (chaînes aléatoires) ... Avez-vous quelque chose à nous dire à ce sujet? En fait, je me demandais quel impact cela aurait à utiliser MyISAM, mais votre excellente réponse m'a fait réaliser que c'était la voie à suivre pour ce cas particulier.
Louis Loudog Trottier
64

Pour une charge avec plus d'écritures et de lectures, vous bénéficierez d'InnoDB. Parce qu'InnoDB fournit un verrouillage de ligne plutôt qu'un verrouillage de table, vos SELECTs peuvent être simultanés, non seulement les uns avec les autres mais également avec de nombreux INSERTs. Cependant, sauf si vous avez l'intention d'utiliser des transactions SQL, définissez le flush de validation InnoDB sur 2 ( innodb_flush_log_at_trx_commit ). Cela vous redonne beaucoup de performances brutes que vous perdriez autrement lors du déplacement des tables de MyISAM vers InnoDB.

Envisagez également d'ajouter une réplication. Cela vous donne une certaine échelle de lecture et puisque vous avez déclaré que vos lectures n'ont pas besoin d'être à jour, vous pouvez laisser la réplication prendre un peu de retard. Assurez-vous simplement qu'il peut rattraper tout sauf le trafic le plus intense ou il sera toujours derrière et ne rattrapera jamais. Si vous procédez de cette façon, cependant, je vous recommande fortement d'isoler la lecture des esclaves et de la gestion du retard de réplication vers votre gestionnaire de base de données. C'est tellement plus simple si le code d'application ne le sait pas.

Enfin, soyez conscient des différentes charges de table. Vous n'aurez pas le même rapport lecture / écriture sur toutes les tables. Certaines tables plus petites avec près de 100% de lectures pourraient permettre de rester MyISAM. De même, si vous avez des tables qui sont à près de 100% en écriture, vous pouvez en bénéficier INSERT DELAYED, mais cela n'est pris en charge que dans MyISAM (la DELAYEDclause est ignorée pour une table InnoDB).

Mais référence pour être sûr.

staticien
la source
4
Est-ce que "InnoDB commit flush" vous parlez innodb_flush_log_at_trx_commit?
ceejayoz
2
J'ai trouvé votre message très utile - merci. Évaluer actuellement quand utiliser MyISAM / InnoDB pour mes tables et votre message a été utile. À votre santé.
starmonkey
2
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html indique: Pour les tables MyISAM, s'il n'y a pas de blocs libres au milieu du fichier de données, les instructions SELECT et INSERT simultanées sont prises en charge. Dans ces circonstances, il est très rare que vous utilisiez INSERT DELAYED avec MyISAM.
tymtam
Poste très informatif. J'avais la même question que les op et je dois dire que votre message m'a mis à l'aise sur ma décision concernant le moteur de base de données. Merci! ++
Joe Majewski
Remarque rapide: le retard n'est plus pris en charge dans 5.7. Vous voudrez peut-être tester avec LOW_PRIORITY à la place.
webmat
59

Pour ajouter à la large sélection de réponses couvrant les différences mécaniques entre les deux moteurs, je présente une étude de comparaison de vitesse empirique.

En termes de vitesse pure, il n'est pas toujours vrai que MyISAM est plus rapide qu'InnoDB, mais d'après mon expérience, il a tendance à être plus rapide pour les environnements de travail PURE READ par un facteur d'environ 2,0 à 2,5 fois. De toute évidence, cela ne convient pas à tous les environnements - comme d'autres l'ont écrit, MyISAM manque de choses telles que les transactions et les clés étrangères.

J'ai fait un peu de benchmarking ci-dessous - J'ai utilisé python pour le bouclage et la bibliothèque timeit pour les comparaisons de temps. Par intérêt, j'ai également inclus le moteur de mémoire, cela donne les meilleures performances à tous les niveaux, bien qu'il ne soit adapté qu'aux tables plus petites (vous rencontrez continuellement The table 'tbl' is fulllorsque vous dépassez la limite de mémoire MySQL). Les quatre types de sélection que je regarde sont:

  1. SELECT vanille
  2. compte
  3. SELECT conditionnels
  4. sous-sélections indexées et non indexées

Tout d'abord, j'ai créé trois tables en utilisant le SQL suivant

CREATE TABLE
    data_interrogation.test_table_myisam
    (
        index_col BIGINT NOT NULL AUTO_INCREMENT,
        value1 DOUBLE,
        value2 DOUBLE,
        value3 DOUBLE,
        value4 DOUBLE,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8

avec «MyISAM» substitué à «InnoDB» et «mémoire» dans les deuxième et troisième tableaux.

 

1) La vanille sélectionne

Requete: SELECT * FROM tbl WHERE index_col = xx

Résultat: match nul

Comparaison des sélections de vanille par différents moteurs de base de données

Leur vitesse est globalement la même et, comme prévu, est linéaire dans le nombre de colonnes à sélectionner. InnoDB semble légèrement plus rapide que MyISAM mais c'est vraiment marginal.

Code:

import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint

db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

lengthOfTable = 100000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)
    cur.execute(insertString3)

db.commit()

# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):

    for x in xrange(numberOfRecords):
        rand1 = randint(0,lengthOfTable)

        selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
        cur.execute(selectString)

setupString = "from __main__ import selectRandomRecords"

# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []

for theLength in [3,10,30,100,300,1000,3000,10000]:

    innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )

 

2) Nombre

Requete: SELECT count(*) FROM tbl

Résultat: MyISAM gagne

Comparaison des dénombrements par différents moteurs de base de données

Celui-ci montre une grande différence entre MyISAM et InnoDB - MyISAM (et la mémoire) garde la trace du nombre d'enregistrements dans la table, donc cette transaction est rapide et O (1). Le temps nécessaire à InnoDB pour compter augmente de manière super-linéaire avec la taille de la table dans la plage que j'ai étudiée. Je soupçonne que bon nombre des accélérations des requêtes MyISAM observées dans la pratique sont dues à des effets similaires.

Code:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to count the records
def countRecords(testTable):

    selectString = "SELECT count(*) FROM " + testTable
    cur.execute(selectString)

setupString = "from __main__ import countRecords"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )

 

3) Sélection conditionnelle

Requete: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

Résultat: MyISAM gagne

Comparaison des sélections conditionnelles par différents moteurs de base de données

Ici, MyISAM et la mémoire fonctionnent à peu près de la même manière et battent InnoDB d'environ 50% pour les tables plus grandes. C'est le genre de requête pour laquelle les avantages de MyISAM semblent être maximisés.

Code:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to perform conditional selects
def conditionalSelect(testTable):
    selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
    cur.execute(selectString)

setupString = "from __main__ import conditionalSelect"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )

 

4) Sous-sélections

Résultat: InnoDB gagne

Pour cette requête, j'ai créé un ensemble supplémentaire de tables pour la sous-sélection. Chacune est simplement deux colonnes de BIGINT, une avec un index de clé primaire et une sans index. En raison de la grande taille de la table, je n'ai pas testé le moteur de mémoire. La commande de création de table SQL était

CREATE TABLE
    subselect_myisam
    (
        index_col bigint NOT NULL,
        non_index_col bigint,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8;

où encore une fois, «MyISAM» est remplacé par «InnoDB» dans le deuxième tableau.

Dans cette requête, je laisse la taille du tableau de sélection à 1000000 et je fais plutôt varier la taille des colonnes sous-sélectionnées.

Comparaison des sous-sélections par différents moteurs de base de données

Ici, InnoDB gagne facilement. Après avoir atteint une table de taille raisonnable, les deux moteurs évoluent linéairement avec la taille de la sous-sélection. L'index accélère la commande MyISAM mais a, de façon intéressante, peu d'effet sur la vitesse InnoDB. subSelect.png

Code:

myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []

def subSelectRecordsIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString = "from __main__ import subSelectRecordsIndexed"

def subSelectRecordsNotIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString2 = "from __main__ import subSelectRecordsNotIndexed"

# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"

cur.execute(truncateString)
cur.execute(truncateString2)

lengthOfTable = 1000000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)

for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE subselect_innodb"
    truncateString2 = "TRUNCATE subselect_myisam"

    cur.execute(truncateString)
    cur.execute(truncateString2)

    # For each length, empty the table and re-fill it with random data
    rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
    rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)

    for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
        insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
        insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)

    db.commit()

    # Finally, time the queries
    innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )

    innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
    myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )

Je pense que le message à retenir de tout cela est que si vous êtes vraiment préoccupé par la vitesse, vous devez comparer les requêtes que vous faites plutôt que de faire des hypothèses sur le moteur qui conviendra le mieux.

StackG
la source
1
la performance n'est pas toujours la seule considération, que diriez-vous d'un graphique sur la stabilité? un moteur n'est bon à rien s'il tombe en panne et ne prend pas en charge les fonctionnalités de base de base de données.
pilavdzice
1
MyISAM bat probablement InnoDB la plupart du temps si le my.cnffichier n'est pas optimisé pour InnoDB. Vous n'avez pas mentionné à quoi my.cnfressemble votre fichier, ce qui est vraiment le facteur le plus important pour les performances d'InnoDB.
itoctopus
Merci itoctopus - j'aimerais en savoir plus sur les optimisations que vous recommandez. Le code complet utilisé dans ces tests est ci-dessus, n'hésitez pas à répéter les expériences avec diverses optimisations et faites-nous savoir si vous trouvez des changements significatifs dans les résultats
StackG
32

Légèrement hors sujet, mais à des fins de documentation et d'exhaustivité, je voudrais ajouter ce qui suit.

En général, l'utilisation d'InnoDB se traduira par une application beaucoup MOINS complexe, probablement aussi plus exempte de bogues. Parce que vous pouvez mettre toute l'intégrité référentielle (contraintes de clé étrangère) dans le modèle de données, vous n'avez pas besoin de près de autant de code d'application que vous en aurez besoin avec MyISAM.

Chaque fois que vous insérez, supprimez ou remplacez un enregistrement, vous DEVEZ vérifier et maintenir les relations. Par exemple, si vous supprimez un parent, tous les enfants doivent également être supprimés. Par exemple, même dans un système de blogging simple, si vous supprimez un enregistrement de blog, vous devrez supprimer les enregistrements de commentaires, les likes, etc. Dans InnoDB, cela se fait automatiquement par le moteur de base de données (si vous avez spécifié les contraintes dans le modèle ) et ne nécessite aucun code d'application. Dans MyISAM, cela devra être codé dans l'application, ce qui est très difficile sur les serveurs Web. Les serveurs Web sont par nature très simultanés / parallèles et parce que ces actions doivent être atomiques et MyISAM ne prend en charge aucune transaction réelle, l'utilisation de MyISAM pour les serveurs Web est risquée / sujette aux erreurs.

De plus, dans la plupart des cas généraux, InnoDB fonctionnera beaucoup mieux, pour plusieurs raisons, l'une d'entre elles pouvant utiliser le verrouillage au niveau de l'enregistrement par opposition au verrouillage au niveau de la table. Non seulement dans une situation où les écritures sont plus fréquentes que les lectures, mais également dans les situations avec des jointures complexes sur de grands ensembles de données. Nous avons remarqué une augmentation des performances 3 fois simplement en utilisant les tables InnoDB sur les tables MyISAM pour les jointures très volumineuses (prenant plusieurs minutes).

Je dirais qu'en général InnoDB (en utilisant un modèle de données 3NF complet avec intégrité référentielle) devrait être le choix par défaut lors de l'utilisation de MySQL. MyISAM ne doit être utilisé que dans des cas très spécifiques. Il fonctionnera probablement moins, ce qui entraînera une application plus grande et plus boguée.

Cela dit. Le datamodelling est un art rarement trouvé chez les webdesigners / -programmers. Aucune infraction, mais cela explique que MyISAM soit tellement utilisé.

Patrick Savalle
la source
31

InnoDB propose:

ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)

Dans InnoDB, toutes les données consécutives à l'exception de TEXT et BLOB peuvent occuper 8 000 octets au maximum. Aucune indexation de texte intégral n'est disponible pour InnoDB. Dans InnoDB, les COUNT (*) (lorsque WHERE, GROUP BY ou JOIN n'est pas utilisé) s'exécutent plus lentement que dans MyISAM car le nombre de lignes n'est pas stocké en interne. InnoDB stocke les données et les index dans un seul fichier. InnoDB utilise un pool de tampons pour mettre en cache les données et les index.

MyISAM propose:

fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)

MyISAM a un verrouillage au niveau de la table, mais pas de verrouillage au niveau des lignes. Aucune transaction. Pas de récupération automatique après incident, mais il offre une fonctionnalité de table de réparation. Aucune contrainte de clé étrangère. Les tables MyISAM sont généralement plus compactes sur le disque par rapport aux tables InnoDB. La taille des tables MyISAM pourrait être encore plus réduite en compressant avec myisampack si nécessaire, mais devenir en lecture seule. MyISAM stocke les index dans un fichier et les données dans un autre. MyISAM utilise des tampons clés pour la mise en cache des index et laisse la gestion de la mise en cache des données au système d'exploitation.

Dans l'ensemble, je recommanderais InnoDB pour la plupart des utilisations et MyISAM pour des utilisations spécialisées uniquement. InnoDB est désormais le moteur par défaut dans les nouvelles versions de MySQL.

Pankaj Khurana
la source
2
fwiw, VARCHAR dans InnoDB peut également aller aux pages de débordement, comme BLOB et TEXT. Tous ces types de données sont stockés de manière similaire en interne.
Bill Karwin
Bon à savoir, @BillKarwin! Nous utilisons beaucoup VARCHAR dans notre application et le fait que VARCHAR contribue à cette limite de ~ 8 Ko était un peu inquiétant.
rinogo
Voir mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb pour plus de détails.
Bill Karwin
La réponse n'est plus à jour car le moteur innodb dans MySQL version 5.6+ supporte également aujourd'hui l' indexation en texte intégral et MySQL 5.5 + / 5.7 + prend également en charge les types de données spatiales (5.5+) et les index spatiaux (r-tee) (5.7+) .. Pour le meilleur support, vous auriez au moins besoin d'avoir la version MySQL 5.7+
Raymond Nijland
25

Si vous utilisez MyISAM, vous n'effectuerez aucune transaction par heure, sauf si vous considérez chaque instruction DML comme une transaction (qui, en tout cas, ne sera ni durable ni atomique en cas de crash).

Je pense donc que vous devez utiliser InnoDB.

300 transactions par seconde, c'est beaucoup. Si vous avez absolument besoin que ces transactions soient durables en cas de panne de courant, assurez-vous que votre sous-système d'E / S peut gérer facilement autant d'écritures par seconde. Vous aurez besoin d'au moins un contrôleur RAID avec cache sauvegardé par batterie.

Si vous pouvez prendre un petit coup de durabilité, vous pouvez utiliser InnoDB avec innodb_flush_log_at_trx_commit défini sur 0 ou 2 (voir les documents pour plus de détails), vous pouvez améliorer les performances.

Il existe un certain nombre de correctifs qui peuvent augmenter la concurrence de Google et d'autres - ceux-ci peuvent être intéressants si vous ne pouvez toujours pas obtenir suffisamment de performances sans eux.

MarkR
la source
24

La question et la plupart des réponses sont obsolètes .

Oui, c'est une histoire de vieilles femmes que MyISAM est plus rapide qu'InnoDB. notez la date de la Question: 2008; c'est maintenant près d'une décennie plus tard. Depuis lors, InnoDB a réalisé des progrès importants en termes de performances.

Le graphique était dramatique pour un cas où MyISAM gagne: COUNT(*) sans une WHEREclause. Mais est-ce vraiment ce que vous passez votre temps à faire?

Si vous exécutez un test de concurrence , InnoDB est très susceptible de gagner, même contreMEMORY .

Si vous effectuez des écritures lors de l'analyse comparative SELECTs, MyISAM et MEMORYsont susceptibles de perdre en raison du verrouillage au niveau de la table.

En fait, Oracle est tellement sûr qu'InnoDB est meilleur qu'ils ont pratiquement supprimé MyISAM de la version 8.0.

La question a été écrite au début du 5.1. Depuis lors, ces versions majeures ont été marquées "Disponibilité générale":

  • 2010: 5,5 (0,8 en décembre)
  • 2013: 5,6 (0,10 en février)
  • 2015: 5,7 (.9 en octobre)
  • 2018: 8,0 (0,11 en avril)

Conclusion: n'utilisez pas MyISAM

Rick James
la source
2
Les avancées de la technologie de base de données MySQL. Et les questions et réponses StackOverflow restent embourbées dans le passé. Les principales différences entre MyISAM et InnoDB concernent moins la «charge» sur le serveur, et davantage la prise en charge de l' intégrité référentielle et des transactions , ainsi que la concurrence et la récupérabilité (+10)
spencer7593
12

Consultez également quelques remplacements de remplacement pour MySQL lui-même:

MariaDB

http://mariadb.org/

MariaDB est un serveur de base de données qui offre une fonctionnalité de remplacement sans rendez-vous pour MySQL. MariaDB est construit par certains des auteurs originaux de MySQL, avec l'aide de la communauté plus large de développeurs de logiciels libres et open source. En plus des fonctionnalités de base de MySQL, MariaDB offre un riche ensemble d'améliorations de fonctionnalités, y compris des moteurs de stockage alternatifs, des optimisations de serveur et des correctifs.

Serveur Percona

https://launchpad.net/percona-server

Un remplacement drop-in amélioré pour MySQL, avec de meilleures performances, des diagnostics améliorés et des fonctionnalités supplémentaires.

Raffineur
la source
1
J'utilise les deux (Percona en production, Maria sur windows-development). ils sont plus rapides et fonctionnent parfaitement.
Moshe L
4
Cela ne répond pas à la question. MariaDB et Percona sont des fourches de MySQL, et utilisent également les moteurs InnoDB et MyISAM.
dr_
12

Veuillez noter que mon éducation et mon expérience formelles sont avec Oracle, alors que mon travail avec MySQL a été entièrement personnel et sur mon propre temps, donc si je dis des choses qui sont vraies pour Oracle mais pas pour MySQL, je m'excuse. Bien que les deux systèmes partagent beaucoup, la théorie / algèbre relationnelle est la même et les bases de données relationnelles sont toujours des bases de données relationnelles, il y a encore beaucoup de différences !!

J'aime particulièrement (ainsi que le verrouillage au niveau des lignes) qu'InnoDB est basé sur les transactions, ce qui signifie que vous pouvez mettre à jour / insérer / créer / modifier / supprimer / etc plusieurs fois pour une "opération" de votre application Web. Le problème qui se pose est que si seulement certaines de ces modifications / opérations finissent par être validées, mais d'autres non, vous vous retrouverez la plupart du temps (selon la conception spécifique de la base de données) avec une base de données avec des données / une structure conflictuelles.

Remarque: Avec Oracle, les instructions de création / modification / suppression sont appelées instructions "DDL" (définition de données) et déclenchent implicitement une validation. Les instructions d'insertion / mise à jour / suppression, appelées "DML" (Manipulation des données), ne sont pas validées automatiquement, mais uniquement lorsqu'une DDL, une validation ou une sortie / sortie est effectuée (ou si vous définissez votre session sur "Auto-validation", ou si votre client s'engage automatiquement). Il est impératif d'en être conscient lorsque vous travaillez avec Oracle, mais je ne sais pas comment MySQL gère les deux types d'instructions. Pour cette raison, je tiens à préciser que je ne suis pas sûr de cela quand il s'agit de MySQL; uniquement avec Oracle.

Un exemple de réussite des moteurs basés sur les transactions:

Disons que moi ou vous êtes sur une page Web pour vous inscrire à un événement gratuit, et l'un des principaux objectifs du système est de n'autoriser que jusqu'à 100 personnes à s'inscrire, car c'est la limite du nombre de places assises pour l'événement. Une fois que 100 inscriptions sont atteintes, le système désactiverait les inscriptions supplémentaires, au moins jusqu'à ce que d'autres annulent.

Dans ce cas, il peut y avoir une table pour les invités (nom, téléphone, e-mail, etc.) et une deuxième table qui suit le nombre d'invités qui se sont inscrits. Nous avons donc deux opérations pour une "transaction". Supposons maintenant qu'après l'ajout des informations invité à la table GUESTS, il y ait une perte de connexion ou une erreur avec le même impact. La table GUESTS a été mise à jour (insérée dans), mais la connexion a été perdue avant que les "places disponibles" puissent être mises à jour.

Nous avons maintenant un invité ajouté à la table des invités, mais le nombre de sièges disponibles est désormais incorrect (par exemple, la valeur est 85 alors qu'elle est en fait 84).

Bien sûr, il existe de nombreuses façons de gérer cela, comme le suivi des sièges disponibles avec "100 moins de lignes dans la table des invités", ou un code qui vérifie que les informations sont cohérentes, etc .... Mais avec une base de données basée sur les transactions moteur tel qu'InnoDB, TOUTES les opérations sont validées, ou AUCUNE d'entre elles ne l'est. Cela peut être utile dans de nombreux cas, mais comme je l'ai dit, ce n'est pas la SEULE façon d'être sûr, non (une belle façon, cependant, gérée par la base de données, pas le programmeur / scénariste).

C'est tout "basé sur les transactions" signifie essentiellement dans ce contexte, sauf si je manque quelque chose - que soit la transaction entière réussit comme il se doit, soit rien n'est changé, car effectuer des modifications partielles seulement pourrait rendre le désordre SÉVÈRE mineur du base de données, peut-être même la corrompre ...

Mais je vais le dire une fois de plus, ce n'est pas le seul moyen d'éviter de faire un gâchis. Mais c'est l'une des méthodes que le moteur lui-même gère, vous laissant coder / script sans avoir à vous soucier de "si la transaction a réussi ou non, et que dois-je faire si non (comme réessayer)", au lieu de manuellement écrire du code pour le vérifier «manuellement» depuis l'extérieur de la base de données, et faire beaucoup plus de travail pour de tels événements.

Enfin, une note sur le verrouillage de table vs le verrouillage de ligne:

AVERTISSEMENT: je peux me tromper dans tout ce qui suit en ce qui concerne MySQL, et les situations hypothétiques / d'exemple sont des choses à examiner, mais je peux me tromper dans ce qui est exactement possible de causer la corruption avec MySQL. Les exemples sont cependant très réels dans la programmation générale, même si MySQL a plus de mécanismes pour éviter de telles choses ...

Quoi qu'il en soit, je suis assez confiant en accord avec ceux qui ont fait valoir que le nombre de connexions sont autorisées à un moment - t pas fonctionne autour d'une table verrouillée. En fait, plusieurs connexions sont le point entier de verrouiller une table !! Pour que d'autres processus / utilisateurs / applications ne puissent pas corrompre la base de données en effectuant des modifications en même temps.

Comment deux connexions ou plus fonctionnant sur la même ligne feraient-elles un JOUR VRAIMENT MAUVAIS pour vous ?? Supposons qu'il y ait deux processus qui veulent / doivent mettre à jour la même valeur dans la même ligne, disons parce que la ligne est un enregistrement d'un tour de bus, et chacun des deux processus veut simultanément mettre à jour les "riders" ou "available_seats" champ comme "la valeur actuelle plus 1."

Faisons cela hypothétiquement, étape par étape:

  1. Le processus 1 lit la valeur actuelle, disons qu'elle est vide, donc '0' jusqu'à présent.
  2. Le processus deux lit également la valeur actuelle, qui est toujours 0.
  3. Processus on écrit (courant + 1) qui est 1.
  4. Le processus deux devrait écrire 2, mais comme il lit la valeur actuelle avant que le processus un n'écrive la nouvelle valeur, il écrit également 1 dans la table.

Je ne suis pas certain que deux connexions puissent se mélanger comme ça, les deux lisant avant la première écrit ... Mais sinon, je verrais toujours un problème avec:

  1. Le processus un lit la valeur actuelle, qui est 0.
  2. Processus on écrit (courant + 1), qui est 1.
  3. Le processus deux lit maintenant la valeur actuelle. Mais alors qu'il traite une écriture DID (mise à jour), il n'a pas validé les données, donc seul ce même processus peut lire la nouvelle valeur qu'il a mise à jour, tandis que tous les autres voient l'ancienne valeur, jusqu'à ce qu'il y ait une validation.

De plus, au moins avec les bases de données Oracle, il existe des niveaux d'isolement, que je ne perdrai pas notre temps à essayer de paraphraser. Voici un bon article sur ce sujet, et chaque niveau d'isolement ayant ses avantages et ses inconvénients, qui irait de pair avec l'importance des moteurs basés sur les transactions dans une base de données ...

Enfin, il peut y avoir différentes protections en place au sein de MyISAM, au lieu des clés étrangères et des interactions basées sur les transactions. Eh bien, pour l' un, il y a le fait qu'une table entière est verrouillée, ce qui rend moins probable que les transactions / FKs sont nécessaires .

Et hélas, si vous êtes conscient de ces problèmes de concurrence, oui, vous pouvez le jouer moins en toute sécurité et simplement écrire vos applications, configurer vos systèmes afin que de telles erreurs ne soient pas possibles (votre code est alors responsable, plutôt que la base de données elle-même). Cependant, à mon avis, je dirais qu'il est toujours préférable d'utiliser autant de sauvegardes que possible, en programmant de manière défensive et en étant toujours conscient que l'erreur humaine est impossible à éviter complètement. Cela arrive à tout le monde, et quiconque se dit à l'abri doit mentir, ou n'a pas fait plus qu'écrire une application / un script "Hello World". ;-)

J'espère que CERTAINS de cela est utile à quelqu'un, et plus encore, j'espère que je n'ai pas seulement été un coupable d'hypothèses et d'être un humain par erreur !! Je vous prie de m'excuser, mais il est bon de réfléchir aux exemples, de rechercher le risque, etc., même s'ils ne sont pas potentiels dans ce contexte spécifique.

N'hésitez pas à me corriger, à modifier cette «réponse», voire à voter contre. S'il vous plaît, essayez d'améliorer, plutôt que de corriger une mauvaise hypothèse avec la mienne. ;-)

Ceci est ma première réponse, alors veuillez pardonner la longueur due à tous les avis de non-responsabilité, etc ... Je ne veux tout simplement pas paraître arrogant quand je ne suis pas absolument certain!

Arembjorn
la source
5

D'après mon expérience, MyISAM était un meilleur choix tant que vous ne faites pas DELETEs, UPDATEs, beaucoup de INSERT unique, des transactions et une indexation de texte intégral. BTW, CHECK TABLE est horrible. À mesure que le tableau vieillit en termes de nombre de lignes, vous ne savez pas quand il se terminera.

yogman
la source
2
L'indexation de texte intégral n'est possible qu'avec MyISAM, pas avec InnoDB.
Pixel Elephant
2
@PixelElephant, cela commence à changer dans MySQL 5.6. InnoDB a un type d'index de texte intégral, mais jusqu'à présent, il n'est pas prêt à être utilisé à la production à mon humble avis.
Bill Karwin
1
"L'indexation de texte intégral n'est possible qu'avec MyISAM, pas avec InnoDB": plus vrai depuis MySQL> = 5.6. Voir dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57
5

J'ai compris que même si Myisam a des conflits de verrouillage, il est toujours plus rapide qu'InnoDb dans la plupart des scénarios en raison du schéma d'acquisition de verrouillage rapide qu'il utilise. J'ai essayé plusieurs fois Innodb et je retombe toujours sur MyIsam pour une raison ou une autre. InnoDB peut également être très gourmand en ressources processeur dans d'énormes charges d'écriture.

Ricardo
la source
4

Chaque application possède son propre profil de performances pour l'utilisation d'une base de données, et il est probable qu'elle changera avec le temps.

La meilleure chose que vous puissiez faire est de tester vos options. Le basculement entre MyISAM et InnoDB est trivial, alors chargez des données de test et déclenchez jmeter sur votre site et voyez ce qui se passe.

Gary Richardson
la source
4

J'ai essayé d'exécuter l'insertion de données aléatoires dans les tables MyISAM et InnoDB. Le résultat a été assez choquant. MyISAM a eu besoin de quelques secondes de moins pour insérer 1 million de lignes qu'InnoDB pour seulement 10 000!

user965748
la source
2
Vous obtiendrez les mêmes performances si vous utilisez la transaction et désactivez la validation automatique pour le moteur InnoDB.
stanleyxu2005
IDK si les mêmes performances, mais c'est ce que je fais dans les applications plus complexes et cela accélère.
user965748
1
Vous n'avez pas fourni les détails exacts de votre test - quels paramètres de configuration? Que contenait le (s) tableau (s) auparavant? Quel genre de données? et peut-être le plus important - y avait-il des insertions séquentielles? Parallèle? Quel était leur timing? Combien de cœurs CPU? Des discussions? etc.
einpoklum
3

myisam est un NOGO pour ce type de charge de travail (écritures à concurrence élevée), je n'ai pas beaucoup d'expérience avec innodb (l'a testé 3 fois et a constaté dans chaque cas que les performances étaient nulles, mais cela fait un certain temps depuis le dernier test) si vous ne sommes pas obligés d'exécuter mysql, pensez à essayer postgres car il gère beaucoup mieux les écritures simultanées

pfote
la source
3

En bref, InnoDB est bon si vous travaillez sur quelque chose qui a besoin d'une base de données fiable capable de gérer de nombreuses instructions INSERT et UPDATE.

et, MyISAM est bon si vous avez besoin d'une base de données qui prendra principalement beaucoup d'instructions de lecture (SELECT) plutôt que d'écriture (INSERT et UPDATES), compte tenu de son inconvénient sur le verrouillage de table.

vous voudrez peut-être vérifier;
Avantages et inconvénients d'InnoDB
Avantages et inconvénients de MyISAM

Light93
la source
2

Je sais que cela ne sera pas populaire, mais voici:

myISAM ne prend pas en charge les éléments essentiels de la base de données tels que les transactions et l'intégrité référentielle, ce qui se traduit souvent par des applications glitchy / buggy. Vous ne pouvez pas ne pas apprendre les principes fondamentaux de la conception d'une base de données s'ils ne sont même pas pris en charge par votre moteur de base de données.

Ne pas utiliser l'intégrité référentielle ou les transactions dans le monde des bases de données, c'est comme ne pas utiliser la programmation orientée objet dans le monde logiciel.

InnoDB existe maintenant, utilisez-le à la place! Même les développeurs MySQL ont finalement accepté de changer cela en moteur par défaut dans les versions plus récentes, bien que myISAM soit le moteur d'origine qui était le moteur par défaut dans tous les systèmes hérités.

Non, peu importe si vous lisez ou écrivez ou quelles sont vos considérations de performances, l'utilisation de myISAM peut entraîner divers problèmes, comme celui-ci que je viens de rencontrer: je faisais une synchronisation de base de données et en même temps quelqu'un d'autre a accédé à une application qui a accédé à une table définie sur myISAM. En raison du manque de prise en charge des transactions et de la fiabilité généralement médiocre de ce moteur, cela a planté toute la base de données et j'ai dû redémarrer manuellement mysql!

Au cours des 15 dernières années de développement, j'ai utilisé de nombreuses bases de données et moteurs. myISAM s'est écrasé sur moi une douzaine de fois au cours de cette période, d'autres bases de données, une seule fois! Et c'était une base de données Microsoft SQL où certains développeurs ont écrit un code CLR défectueux (un langage d'exécution commun - essentiellement du code C # qui s'exécute à l'intérieur de la base de données), d'ailleurs, ce n'était pas exactement la faute du moteur de base de données.

Je suis d'accord avec les autres réponses ici qui disent que les applications de haute disponibilité et haute performance de qualité ne devraient pas utiliser myISAM car il ne fonctionnera pas, il n'est pas suffisamment robuste ou stable pour aboutir à une expérience sans frustration.Voir la réponse de Bill Karwin pour plus de détails.

PS Je dois l'adorer quand les fans de myISAM dévalorisent mais ne peuvent pas vous dire quelle partie de cette réponse est incorrecte.

pilavdzice
la source
5
je n'ai pas downvote, mais si je le faisais ce serait pour conseiller de ne jamais utiliser. le mot ne devrait jamais être supprimé dans le vocabulaire d'un développeur ... la mise en garde étant «ne jamais dire jamais».
hubson bropa
1

Pour ce rapport lecture / écriture, je suppose que InnoDB fonctionnera mieux. Puisque vous êtes bien avec des lectures sales, vous pouvez (si vous en avez les moyens) répliquer vers un esclave et laisser toutes vos lectures aller vers l'esclave. Envisagez également d'insérer en bloc plutôt qu'un enregistrement à la fois.

neal aise
la source
1

Presque chaque fois que je démarre un nouveau projet, je recherche sur Google la même question pour voir si je trouve de nouvelles réponses.

Cela se résume finalement à - je prends la dernière version de MySQL et exécute des tests.

J'ai des tables où je veux faire des recherches de clé / valeur ... et c'est tout. J'ai besoin d'obtenir la valeur (0-512 octets) pour une clé de hachage. Il n'y a pas beaucoup de transactions sur cette BD. Le tableau obtient des mises à jour occasionnellement (dans son intégralité), mais 0 transactions.

Nous ne parlons donc pas d'un système complexe ici, nous parlons d'une simple recherche, .. et de la façon (autre que de faire de la RAM de la table résidente) nous pouvons optimiser les performances.

Je fais également des tests sur d'autres bases de données (ie NoSQL) pour voir s'il y a un endroit où je peux obtenir un avantage. Le plus grand avantage que j'ai trouvé est dans le mappage des clés, mais en ce qui concerne la recherche, MyISAM est actuellement en tête de tous.

Bien que je n'effectue pas de transactions financières avec les tables MyISAM, mais pour les recherches simples, vous devriez le tester .. généralement 2x à 5x les requêtes / sec.

Testez-le, j'accueille favorablement le débat.

Cyberwip
la source
1

Si c'est 70% d'inserts et 30% de lectures, cela ressemble plus au côté InnoDB.

kta
la source
0

Conclusion: si vous travaillez hors ligne avec des sélections sur de gros morceaux de données, MyISAM vous donnera probablement de meilleures (bien meilleures) vitesses.

il y a des situations où MyISAM est infiniment plus efficace qu'InnoDB: lors de la manipulation de gros vidages de données hors ligne (à cause du verrouillage de la table).

exemple: je convertissais un fichier csv (15 millions d'enregistrements) de NOAA qui utilise les champs VARCHAR comme clés. InnoDB prenait une éternité, même avec de gros morceaux de mémoire disponibles.

c'est un exemple de csv (les premier et troisième champs sont des clés).

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

puisque ce que je dois faire est d'exécuter une mise à jour par lots hors ligne des phénomènes météorologiques observés, j'utilise la table MyISAM pour recevoir des données et exécuter JOINS sur les clés afin de pouvoir nettoyer le fichier entrant et remplacer les champs VARCHAR par des clés INT (qui sont liées à tables externes où les valeurs VARCHAR d'origine sont stockées).

Tony Gil
la source