web-dev-qa-db-fra.com

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

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

Pourquoi devrait-il différer des inserts normaux?

MODIFIER:
J'ai réduit l'aller-retour en appelant une seule instruction INSERT:

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?

22
ALH

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 de lignes, INSERT étendu est judicieux.

Notez que mysqldump a été conçu autour d'inserts étendus dans le but de transporter la conception de table avec des 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 utilisée, vous devez toujours définir bulk_insert_buffer_size . Pourquoi?

Selon la documentation MySQL sur bulk_insert_buffer_size:

MyISAM utilise un cache arborescent spécial pour accélérer les insertions en masse 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 depuis un fichier bloqué en attente sur le disque dur

26
RolandoMySQLDBA

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 instruction INSERT contient une quantité importante de bagages par instruction - verrouillage, démarcation des transactions, contrôles d'intégrité référentielle, allocation des ressources, E/S qui doivent être effectuées sur une base par instruction.

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.

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

Chaque instruction INSERT 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 bloc via LOAD DATA INFILE. Il existe également des optimisations qui peuvent avoir lieu lors de l'utilisation de LOAD DATA INFILE pour charger dans une table vide. Voir ce lien pour plus d'informations.

3
Philᵀᴹ