Pourquoi «LOAD DATA INFILE» est-il plus rapide que les instructions INSERT normales?

22

J'ai lu un article qui mentionnait que nous pouvons réaliser 60 000 insertions par seconde en utilisant l' LOAD DATA IN FILEinstruction, qui lit à partir de fichiers csv et insère les données dans une base de données.

Pourquoi devrait-il différer des inserts normaux?

EDIT:
J'ai réduit l'aller-retour en appelant une seule INSERTdéclaration:

INSERT INTO tblname
VALUES (NULL,2,'some text here0'),(NULL,2,'some text here1')
    ,(NULL,2,'some text here2'),(NULL,2,'some text here3')
    .....,(NULL,2,'some text here3000');

Et ça?

ALH
la source
J'ai écrit un article sur moyen, analyses comparatives Insertions étendues vs LOAD DATA INFILE: inserts à grande vitesse avec MySQL . Conclusion: vous pouvez obtenir 65% des performances de l' LOAD DATA INFILEutilisation d'inserts allongés. J'ai obtenu 240 000 insertions / seconde sur du matériel moderne.
Benjamin

Réponses:

26

LOAD DATA INFILE et INSERT étendus ont chacun leurs avantages distincts.

LOAD DATA INFILE est conçu pour charger en masse des données de table en une seule opération avec des cloches et des sifflets pour effectuer des tings comme:

  • Ignorer les lignes initiales
  • Ignorer des colonnes spécifiques
  • Transformation de colonnes spécifiques
  • Chargement de colonnes spécifiques
  • Gestion des problèmes clés en double

Moins de frais généraux sont nécessaires pour l'analyse

D'un autre côté, si vous importez seulement 100 lignes au lieu de 1 000 000 lignes, INSERT étendu est judicieux.

Notez que mysqldump a été conçu autour des INSERT étendus pour transporter la conception de la table avec les données car il effectue l'injection de centaines ou de milliers de lignes par INSERT. LOAD DATA INFILE crée toujours une dichomotie physique entre le schéma et les données.

Du point de vue de l'application, LOAD DATA INFILE est également plus insensible aux modifications de schéma que les INSERT étendus.

On peut aller et venir sur le bon, le mauvais et le laid de l'utilisation de LOAD DATA INFILE. Quelle que soit la technique que vous utilisez, vous devez toujours définir la taille bulk_insert_buffer_size . Pourquoi?

Selon la documentation MySQL sur bulk_insert_buffer_size:

MyISAM utilise un cache en forme d'arbre spécial pour accélérer les insertions en bloc pour INSERT ... SELECT, INSERT ... VALUES (...), (...), ... et LOAD DATA INFILE lors de l'ajout de données à non vide les tables. Cette variable limite la taille de l'arborescence du cache en octets par thread. Le mettre à 0 désactive cette optimisation. La valeur par défaut est 8 Mo.

Pendant des années, j'ai vu client après client ne pas régler cela et le laisser à 8 Mo. Puis, lorsqu'ils décident d'utiliser LOAD DATA INFILE ou d'importer mysqldumps, ils peuvent détecter quelque chose de mal. Je recommande généralement de le régler sur un 256M modéré. Dans certains cas, 512M.

Une fois que vous avez un tampon INSERT en vrac suffisamment grand, l'utilisation de l'une ou l'autre technique est rendue académique et se résume à un choix personnel. Pour les applications où vous insérez en vrac seulement 100 lignes à la demande, respectez les insertions étendues.

En toute honnêteté, dire LOAD DATA INFILE est plus rapide que les instructions INSERT normales est une sorte d'instruction chargée principalement parce que la configuration n'est pas prise en compte. Même si vous configurez une analyse comparative entre LOAD DATA INFILE et les INSERT étendus avec un bulk_insert_buffer_size approprié, les nanosecondes enregistrées lors de l'analyse de chaque ligne ne peuvent donner au mieux que des résultats nominaux en faveur de LOAD DATA INFILE.

Allez-y et ajoutez ceci à my.cnf

[mysqld]
bulk_inset_buffer_size=256M

Vous pouvez également le configurer uniquement pour votre session avant de lancer des INSERT étendus

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

MISE À JOUR 2012-07-19 14:58 EDT

Pour garder les choses en perspective, le tampon d'insertion en bloc n'est utile que pour le chargement des tables MyISAM, pas InnoDB. J'ai écrit un article plus récent sur le chargement en vrac InnoDB: charge Mysql à partir d'un fichier bloqué en attente sur le disque dur

RolandoMySQLDBA
la source
4

La plupart des systèmes de gestion de base de données ont une fonction de chargement en masse pour charger rapidement de gros volumes de données. Une INSERTdéclaration contient une quantité importante de bagages par déclaration - verrouillage, démarcation des transactions, contrôles d'intégrité référentielle, allocation des ressources, E / S qui doivent être effectuées sur la base d'une déclaration.

Les opérations d'insertion en bloc rationalisent le processus, ce qui a beaucoup, beaucoup moins de frais généraux par ligne. Un SGBD peut charger en masse des ordres de grandeur de données plus rapidement que par le biais d'instructions d'insertion.

ConcernedOfTunbridgeWells
la source
3

L'analyse et l'exécution des INSERTinstructions individuelles entraînent une charge beaucoup plus importante que la division d'un fichier CSV en colonnes et leur chargement direct.

Chaque INSERTinstruction doit être analysée individuellement par le moteur MySQL et vérifiée pour sa validité - cela consomme des ressources CPU supplémentaires et nécessite également plus d'allers-retours client <> serveur. Cela ne doit pas se produire lors du chargement en masse via LOAD DATA INFILE. Il existe également des optimisations qui peuvent avoir lieu lors de l'utilisation LOAD DATA INFILEpour charger dans une table vide. Voir ce lien pour plus d'informations.

Philᵀᴹ
la source
voir la partie EDIT de ma question.
ALH
Notez qu'il n'y a pas de surcharge d'analyse lors de l'utilisation d'instructions préparées.
Benjamin