it-swarm.com.de

Doctrine2 - Mehrere Einsätze in einem Schuss

Ich bin neu in der Lehre und es gibt immer noch einige verschwommene Bereiche für mich. In diesem Fall füge ich mit einer Schleife und dem Entitätsmanager einen neuen Datensatz in die Datenbank ein. Es funktioniert gut, aber ich habe festgestellt, dass Doctrine eine Einfüge-Abfrage nach Entität vornimmt, was ziemlich groß werden kann.

Wenn Sie Doctrine2 und Symfony 2.3 verwenden, würde ich gerne wissen, wie wir es einrichten können, damit nur eine Einfügeabfrage mit allen darin enthaltenen Werten erstellt wird (wir sprechen hier natürlich nur von einer Entität).

Was ich meine, ändert das:

INSERT INTO dummy_table VALUES (x1, y1)    
INSERT INTO dummy_table VALUES (x2, y2)

In

INSERT INTO dummy_table VALUES (x1, y1), (x2, y2)

Hier ist mein Code:

$em = $this->container->get('doctrine')->getManager();

foreach($items as $item){
    $newItem = new Product($item['datas']);
    $em->persist($newItem);
}

$em->flush();
20
Molkobain

Laut dieser Antwort erlaubt Doctrine2 nicht, mehrere INSERT-Anweisungen zu einer zu kombinieren:

Einige Leute scheinen sich zu fragen, warum Doctrine .__ nicht verwendet. Multi-Inserts (Einfügen in (...) Werte (...), (...), (...), ...

Zuallererst wird diese Syntax nur von mysql und neueren .__ unterstützt. Postgresql-Versionen. Zweitens gibt es keine einfache Möglichkeit, alle die generierten Bezeichner in einem solchen Multi-Insert, wenn .__ verwendet wird. AUTO_INCREMENT oder SERIAL und ein ORM benötigt die Identifikatoren für die Identität Verwaltung der Objekte. Letztendlich ist Insert-Performance selten die Engpass eines ORM. Normale Inserts sind mehr als schnell genug für In den meisten Situationen und wenn Sie wirklich schnelle Masseneinfügungen machen wollen, dann eine Multi-Insert ist ohnehin nicht der beste Weg, d. h. Postgres COPY oder Mysql LOAD DATA INFILE sind mehrere Größenordnungen schneller.

Dies sind die Gründe, warum es sich nicht lohnt, ein .__ zu implementieren. Abstraktion, die mehrere Einfügungen für mysql und postgresql in einer .__ ausführt. ORM.

Weitere Informationen zur Doctrine2-Stapelverarbeitung finden Sie hier: http://www.doctrine-project.org/blog/doctrine2-batch-processing.html

Sie können entweder zu DBAL wechseln oder Ihre Daten in kleinen Batches verarbeiten, indem Sie Ihren Entitätsmanager nach einer bestimmten Anzahl von Einfügungen leeren:

$batchSize = 20;

foreach ($items as $i => $item) {
     $product = new Product($item['datas']);

     $em->persist($product);

     // flush everything to the database every 20 inserts
     if (($i % $batchSize) == 0) {
         $em->flush();
         $em->clear();
    }
}

// flush the remaining objects
$em->flush();
$em->clear();
38
ukliviu

Sie können diese Gabel https://github.com/stas29a/doctrine2 ausprobieren. Es implementiert genau das, was Sie wollen. Ich habe es in MySQL getestet und es funktioniert gut und 5 mal schneller als diese Stapelverarbeitung. Diese Gabel erhält eine erste eingefügte ID und erhöht sie in PHP, um andere IDs zu erhalten. Es funktioniert in den meisten Fällen aber nicht in allen. Sie müssen also wissen, was Sie tun, wenn Sie diese Gabel verwenden.

2
s29a

Sie können die executeUpdate($query, array $params = array(), array $types = array())-Methode der DriverConnection-Schnittstelle verwenden, um diese Aktion auszuführen. Es ist jedoch etwas schwierig, mehrere Parameter zu binden.

Daten:

$postMetaData = [
    [
        'post_id' => $product->getId(),
        'meta_key' => '_visibility',
        'meta_value' => 'visible',
    ],
    [
        'post_id' => $product->getId(),
        'meta_key' => '_stock_status',
        'meta_value' => $insert['in_stock'] ? 'instock' : 'outofstock',
    ]
];

Massenaktualisierungsmethode:

public function updateOrCreateBulk($posts, \Doctrine\DBAL\Connection $connection)
{

    $placeholders = [];
    $values = [];
    $types = [];

    foreach ($posts as $columnName => $value) {
        $placeholders[] = '(?)';
        $values[] = array_values($value);
        $types[] = \Doctrine\DBAL\Connection::PARAM_INT_ARRAY;
    }

    return $connection->executeUpdate(
        'INSERT INTO `wp_postmeta` (`post_id`, `meta_key`, `meta_value`)  VALUES ' . implode(', ', $placeholders) . ' ON DUPLICATE KEY UPDATE `meta_value` = VALUES(`meta_value`)',
        $values,
        $types
    );
}
0
Sviat