“INSÉRER IGNORER” vs “INSÉRER ... SUR un DOUBLE de la CLÉ de mise à JOUR”
Lors de l'exécution d'un INSERT
instruction avec beaucoup de lignes, je veux sauter en double entrées qui pourrait entraîner une défaillance. Après quelques recherches, mes options semblent être l'utilisation de:
ON DUPLICATE KEY UPDATE
qui implique un jour inutile à un certain coût, ouINSERT IGNORE
qui implique une invitation pour d'autres types de non-glissement dans l'improviste.
Suis-je droit à ces hypothèses? Quelle est la meilleure façon de simplement ignorer les lignes qui pourrait provoquer des doublons et juste continuer sur les autres lignes?
Vous devez vous connecter pour publier un commentaire.
Je vous conseille d'utiliser
INSERT...ON DUPLICATE KEY UPDATE
.Si vous utilisez
INSERT IGNORE
, la ligne ne sera pas réellement être inséré si elle aboutit à un double de la clé. Mais la déclaration ne génère pas une erreur. Il génère un avertissement à la place. Ces cas comprennent:PRIMARY KEY
ouUNIQUE
contraintes.NOT NULL
contrainte.Si vous utilisez
REPLACE
, MySQL est en fait unDELETE
suivie par unINSERT
en interne, qui a des effets secondaires inattendus:REPLACE
.DELETE
sont exécutées inutilement.correction: les deux
REPLACE
etINSERT...ON DUPLICATE KEY UPDATE
sont non-standard, propriétaire des inventions propres à MySQL. ANSI SQL 2003 définit unMERGE
déclaration qui peut résoudre le même besoin (et plus), mais MySQL ne prend pas en charge laMERGE
déclaration.Un utilisateur a tenté de modifier ce post (le montage a été rejeté par les modérateurs). L'édition essayé d'ajouter une revendication qui
INSERT...ON DUPLICATE KEY UPDATE
provoque une nouvelle auto-incrément id alloués. Il est vrai que la nouvelle carte d'identité est généré, mais il n'est pas utilisé dans la ligne modifiée.Voir démonstration ci-dessous, testé avec Percona Server 5.5.28. La variable de configuration
innodb_autoinc_lock_mode=1
(par défaut):Ci-dessus montre que la IODKU déclaration détecte les doublons, et appelle la mise à jour pour modifier la valeur de
u
. Remarque leAUTO_INCREMENT=3
indique un id a été généré, mais pas utilisé dans la ligne.Alors que
REPLACE
ne supprimez la ligne d'origine et insère une nouvelle ligne, générant et d'enregistrer un auto-incrément id:INSERT IGNORE
sur MySQL 5.5.19 phpMyAdmin 3.4.9 et il ne génère pas d'alerte. Quelqu'un pourrait-il confirmer siINSERT IGNORE
génère des avertissements dans les versions actuelles?INSERT ... ON DUPLICATE KEY UPDATE ...
consolidés. Beaucoup des données est double, et il a entraîné dans une seule instance de l'IA PK augmentation de 17,029,941 à 46,271,740 entre les deux lignes. Cette génération de une nouvelle IA à chaque fois signifie que votre gamme peut très vite être rempli et vous avez besoin de nettoyer. Cette table est à seulement deux semaines!SHOW SESSION STATUS LIKE 'Handler%';
pour voir combien de lignes sont lues, écrites et mises à jour.on duplicate key
incréments handler_read_rnd, tandis queinsert ignore
ne le fait pas. Cependant, je n'ai pas vérifier pour voir si la différence était plus marquée que cela (c'est à dire avec de multiples indices, sont-ils tous mis à jour avec le double de la mise à jour, ou probablement pas.) Ma conjecture:insert ignore
pourrait être beaucoup plus rapides sous la charge.on duplicate key update
ne peut pas avoir. Voir mon commentaire dans le stackoverflow.com/questions/6291405/...)Dans le cas où vous voulez voir ce que tout ceci signifie, ici, est un coup-par-coup de tout:
Clé primaire est basée sur les deux colonnes de ce tableau de référence rapide. Une clé Primaire nécessite des valeurs uniques.
Commençons:
note, ci-dessus enregistré trop de travail supplémentaire par le réglage de la colonne égale à elle-même, aucune mise à jour nécessaire
et plusieurs lignes de tests:
pas d'autres messages ont été générés dans la console, et il dispose maintenant de ces 4 valeurs dans le tableau de données. J'ai supprimé tout à l'exception de (1,1) donc j'ai pu tester de la même terrain de jeu
Donc là vous l'avez. Depuis cet été toutes réalisées sur une nouvelle table avec presque pas de données et non pas dans la production, à la fois pour l'exécution ont été microscopique et hors de propos. N'importe qui avec des données du monde réel serait plus que le bienvenu pour participer il.
INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
.Quelque chose d'important à ajouter: Lors de l'utilisation d'INSÉRER IGNORER et vous avez des violations de clé, MySQL n'est PAS un avertissement!
Si vous essayez par exemple d'insérer 100 enregistrements à la fois, avec une défaillant, vous obtiendrez en mode interactif:
Comme vous le voyez: Pas de mise en garde! Ce comportement est le même, à tort, décrit dans le Documentation de Mysql.
Si votre script doit être informé, si certains enregistrements n'ont pas été ajoutés (en raison de violations de clé), vous devez appeler mysql_info() et de l'analyser pour les "Doublons" de la valeur.
mysqli_affected_rows()
pour savoir si leINSERT
s'est réellement passé.Cannot add or update a child row: a foreign key constraint fails
et pas de lignes (même celles valides) sont ajoutés.INSERT IGNORE
, des doubles de clés sont ignorés avec aucune erreur ou d'avertissement.J'utilise régulièrement les
INSERT IGNORE
, et il semble que c'est exactement le genre de comportement que vous cherchez ainsi. Tant que vous savez que les lignes qui serait la cause de l'indice des conflits ne peut être inséré et vous planifiez votre programme en conséquence, il ne devrait pas causer d'ennuis.Je sais que c'est vieux, mais je vais ajouter cette remarque dans le cas où quelqu'un d'autre (comme moi) arrive à cette page, tout en essayant de trouver des informations sur l'INSERTION..IGNORER.
Comme mentionné ci-dessus, si vous utilisez INSERT..IGNORER, les erreurs qui se produisent lors de l'exécution de l'instruction INSERT sont traités comme des avertissements à la place.
Une chose qui n'est pas explicitement mentionné, c'est que l'INSERTION..IGNORER entraînera des valeurs non valides seront ajustés à la plus proche des valeurs lors de l'insertion (alors que les valeurs non valides serait la cause de la requête pour annuler si l'IGNORER le mot clé n'a pas été utilisé).
SUR le DOUBLE de la CLÉ de mise à JOUR n'est pas vraiment dans la norme. C'est aussi standard que de REMPLACER les est. Voir DE FUSION SQL.
Essentiellement ces deux commandes sont alternative-syntaxe versions de commandes standard.
Remplacer
Dans qui semble être une option. Ou vous pouvez vérifier avecCela permettra d'insérer ou de supprimer puis l'insérer. J'ai tendance à aller pour un
IF NOT EXISTS
vérifier d'abord.REPLACE
supprime toutes les lignes dans le tableau correspondant à aucunPRIMARY
ouUNIQUE
clé, puisINSERTs
. C'est potentiellement beaucoup plus de travail alors IODKU.Si vous utilisez
insert ignore
avoir unSHOW WARNINGS;
déclaration à la fin de votre requête ensemble montrera un tableau avec toutes les mises en garde, y compris les Id qui ont été les doublons.SHOW WARNINGS;
ne semble affecter la dernière requête. Toutes les déclarations antérieures ne sont pas accumulés, si vous avez plus d'une seule instruction.Danger potentiel d'INSÉRER IGNORER.
Si vous essayez d'insérer une valeur VARCHAR plus longue de la colonne a été défini avec la valeur sera tronqué et inséré, MÊME SI le mode strict est activé.
Si vous souhaitez insérer dans le tableau et sur le conflit de la clé primaire ou unique de l'index, il fera la mise à jour de la ligne en conflit au lieu d'insérer cette ligne.
Syntaxe:
Maintenant, ici, cette instruction insert peut être différent de ce que vous avez vu plus tôt. Cette instruction insert en essayant d'insérer une ligne dans le tableau 1 avec la valeur de a et de b dans la colonne colonne1 et colonne2 respectivement.
Nous allons comprendre cette affirmation, profondeur:
Par exemple: ici colonne1 est défini comme clé primaire dans la table table1.
Maintenant, si dans table1 il n'y a pas de ligne ayant la valeur “a” dans colonne1. Si cette déclaration va insérer une ligne dans la table1.
Maintenant, si dans table1 il y a une ligne ayant la valeur “a” dans colonne2. Si cette déclaration sera mise à jour de la ligne de la colonne2 valeur avec un “c” où la colonne1 valeur est “une”.
Donc, si vous voulez insérer une nouvelle ligne de mise à jour de la ligne sur le conflit de la clé primaire ou unique index.
En lire plus sur ce lien
INSERT...ON DUPLICATE KEY UPDATE
est préférable d'éviter toute erreur de gestion des Exceptions.Cette solution fonctionne lorsque vous avez **1 contrainte unique** seulement
Dans mon cas, je sais que
col1
etcol2
faire un unique indice composite.Il garde la trace de l'erreur, mais ne jetez pas une exception sur un double.
Concernant les performances, la mise à jour par la même valeur est efficace comme MySQL avis cela et ne pas le mettre à jour
L'idée d'utiliser cette approche est venu à partir des commentaires à phpdelusions.net/pdo.