Traitement Batch


Table des matières

Référence
Inserts en masse
Mise à jour de masse
Mise à jour DQL
Itération de résultats
Suppression en masse
Supprimer par DQL
Itération de résultats
Itération de grands résultats de traitement de données

Référence

http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/batch-processing.html

Ce chapitre vous montre comment accomplir vrac insertions, mises à jour et supprime avec la Doctrine de manière efficace. Le principal problème avec les opérations en bloc ne sont généralement pas à court de mémoire et cela est surtout ce que les stratégies présentées ici fournissent aide.

Un outil ORM n'est pas principalement bien adapté pour les insertions de masse, mises à jour ou suppressions. Chaque SGBDR a sa propre façon ces opérations et si les options décrites ci-dessous ne sont pas suffisantes pour vos besoins, nous vous recommandons d'utiliser les outils pour votre SGBDR particulier pour ces opérations en masse.

Inserts en masse

Les inserts en masse dans Doctrine sont mieux réalisées dans des lots, en tirant parti du comportement de l'écriture transactionnelle d'un EntityManager. Le code suivant montre un exemple d'insertion de 10 000 objets d'une taille de 20 par lot. Vous pouvez avoir besoin d'expérimenter avec la taille du lot à trouver la taille qui vous convient le mieux. Agrandir la taille des lots signifie réutilisation déclaration plus préparés à l'interne, mais aussi signifier plus de travail durant le flush.

<?php
$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
    $user = new CmsUser;
    $user->setStatus('user');
    $user->setUsername('user' . $i);
    $user->setName('Mr.Smith-' . $i);
    $em->persist($user);
    if (($i % $batchSize) == 0) {
        $em->flush();
        $em->clear(); // Detaches all objects from Doctrine!
    }
}

Mise à jour de masse

Il y a 2 possibilités pour les mises à jour de masse avec Doctrine.

Mise à jour DQL

La façon de loin la plus efficace pour les mises à jour de masse est d'utiliser une requête UPDATE DQL. Exemple:

<?php
$q = $em->createQuery('update MyProject\Model\Manager m set m.salary = m.salary * 0.9');
$numUpdated = $q->execute();

Itération de résultats

Une solution alternative pour les mises à jour de masse est d'utiliser Query#iterate() qui facilite les itérerations étape par étape des résultats de requête par étape au lieu de charger le résultat entier en mémoire à la fois. L'exemple suivant montre comment faire cela, en combinant l'itération avec la stratégie de batch qui a été déjà utilisé pour les inserts de masse:

<?php
$batchSize = 20;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach($iterableResult AS $row) {
    $user = $row[0];
    $user->increaseCredit();
    $user->calculateNewBonuses();
    if (($i % $batchSize) == 0) {
        $em->flush(); // Executes all updates.
        $em->clear(); // Detaches all objects from Doctrine!
    }
    ++$i;
}

Les itérations ne sont pas possible avec les jointures. La nature de ces jeux de résultats SQL n'est pas adapté pour une hydratation incrémentale.

Suppression en masse

Il ya deux possibilités pour les suppressions en masse avec Doctrine. Vous pouvez soit lancer une requête simple DQL DELETE ou vous pouvez parcourir les résultats et les enlever un à un.

Supprimer par DQL

La façon de loin la plus efficace pour les suppressions de masse est d'utiliser une requête DQL DELETE.

Exemple:

<?php
$q = $em->createQuery('delete from MyProject\Model\Manager m where m.salary > 100000');
$numDeleted = $q->execute();

Itération de résultats

Une solution alternative pour les suppressions de masse est d'utiliser la Query#iterate() qui facilite les itérerations étape par étape des résultats de requête par étape au lieu de charger le résultat entier en mémoire à la fois. L'exemple suivant montre comment faire cela:

<?php
$batchSize = 20;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {
    $em->remove($row[0]);
    if (($i % $batchSize) == 0) {
        $em->flush(); // Executes all deletions.
        $em->clear(); // Detaches all objects from Doctrine!
    }
    ++$i;
}

Les itérations ne sont pas possible avec les jointures. La nature de ces jeux de résultats SQL n'est pas adapté pour une hydratation incrémentale.

Itération de grands résultats de traitement de données

Vous pouvez utiliser la méthode iterate() juste pour itérer sur un résultat important et aucune intention de UPDATE ou DELETE. L'instance IterableResult retour de $query->iterate() implémente l'interface Iterator de sorte que vous pouvez traiter un grand résultat, sans problèmes de mémoire en utilisant l'approche suivante:

<?php
$q = $this->_em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach ($iterableResult AS $row) {
    // do stuff with the data in the row, $row[0] is always the object

    // detach from Doctrine, so that it can be Garbage-Collected immediately
    $this->_em->detach($row[0]);
}

Les itérations ne sont pas possible avec les jointures. La nature de ces jeux de résultats SQL n'est pas adapté pour une hydratation incrémentale.