web-dev-qa-db-fra.com

Pourquoi TRANSACTION / COMMIT améliore-t-il tant les performances avec PHP / MySQL (InnoDB)?

J'ai travaillé avec l'importation de gros fichiers CSV de données; généralement moins de 100 000 enregistrements. Je travaille avec PHP et MySQL (tables InnoDB). J'avais besoin d'utiliser PHP pour transformer certains champs et faire du traitement de texte avant MySQL INSERTs (partie de process_note_data() dans le code ci-dessous). Le LOAD DATA de MySQL n'était pas réalisable, donc ne le suggérez pas.

J'ai récemment essayé d'améliorer la vitesse de ce processus en utilisant des transactions MySQL en utilisant START TRANSACTION Et COMMIT. L'augmentation des performances a été surprenante. Le ou les temps de traitement ont chuté d'un facteur 20. Ainsi, un processus de 20 minutes n'a pris qu'environ 1 minute.

DES QUESTIONS.

1.) Quelqu'un comprend-il pourquoi il y a eu une telle augmentation des performances (20 min à 1 min)?

2.) Dois-je m'inquiéter de l'ampleur de la transaction avec 100 000 enregistrements?

3.) Dois-je m'inquiéter d'un grand nombre d'insertions et/ou de mises à jour dans la transaction?

/*
 * Customer Notes Data:
 * Rows are either a meeting, call or note!
 */
$row = 1;
$data = array();
$fields = array();
$line = '';

$db->query('SET autocommit=0;');
$db->query('START TRANSACTION;');

if (($handle = fopen("modules/".$currentModule."/Data/customernote.csv", "r")) !== FALSE) {
  while (($data = fgetcsv($handle, 4096, ',', '"')) !== FALSE && $row < 999000) {
    //Row 1 - CSV header row with field names
    if ($row == 1) {
      $csv_fields = $data;
    } elseif ($row > 1) {
      $fields = $this->process_note_data($data, $csv_fields, $row);
    }
    $row++;
  } // end while
  fclose($handle);
}

$db->query('COMMIT;');
$db->query('SET autocommit=1;');

Remarque: Le traitement de texte/champ est effectué dans l'appel à $this->process_note_data() qui appelle ensuite une autre classe d'assistance qui a le code d'instruction INSERT. Je n'avais pas assez de place pour inclure tout le code. $db->query() est un objet de base de données typique pour les requêtes MySQL.

32
jjwdesign
  1. Veuillez vérifier ce lien:

    https://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-transaction-management.html

    InnoDB doit vider le journal sur le disque à chaque validation de transaction si cette transaction a apporté des modifications à la base de données. Lorsque chaque modification est suivie d'une validation (comme avec le paramètre de validation automatique par défaut), le débit d'E/S du périphérique de stockage limite le nombre d'opérations potentielles par seconde.

  2. Les transactions importantes peuvent affecter les performances lors de la validation (vérifiez ci-dessus)

  3. Seulement en cas de retour en arrière, cependant il peut être optimisé en utilisant certains paramètres (vérifiez le lien)

22
MiGro

Mon propre petit test en .Net (4 champs par enregistrements):

INSÉRER 1 enregistrement, aucune transaction: 6 ms

INSÉRER 1 enregistrement, en utilisant la transaction: 158 ms

INSÉRER 200 enregistrements à l'aide de transactions, valider après chaque enregistrement: 17778 ms

INSÉRER 200 enregistrements sans aucune transaction: 494 ms

INSÉRER 200 enregistrements à l'aide de transactions, valider uniquement après le dernier enregistrement: 4552 ms

INSÉRER 1000 enregistrements à l'aide de transactions, valider uniquement après le dernier enregistrement: 21795 ms

Client au Danemark, serveur en Belgique (Google cloud f1-micro).

Je voulais mettre cela dans un commentaire mais le formatage n'est pas bon .... alors voici mes excuses à l'avance ;-)

18
MrCalvin