programing

독트린2 - 한 발에 여러 번 삽입

instargram 2023. 10. 29. 19:00
반응형

독트린2 - 한 발에 여러 번 삽입

저는 독트린을 처음 접했는데 아직도 제게 흐릿한 부분이 좀 있습니다.이 경우 저는 루프와 엔티티 관리자를 사용하여 데이터베이스에 새로운 레코드를 삽입합니다.잘 작동하지만 독트린이 개체별로 하나의 삽입 쿼리를 만들어 상당히 커질 수 있다는 것을 알게 되었습니다.

독트린 2와 심포니 2.3을 사용하여 모든 값이 포함된 삽입 쿼리를 1개만 만들 수 있도록 설정하는 방법을 알고 싶습니다(물론 1개 개체에 대해서만 이야기하고 있습니다).

내 말은 이것을 바꾼다는 것입니다.

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

안으로

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

여기 내 코드가 있습니다.

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

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

$em->flush();

이 답변에 따르면, Driot2에서는 여러 INSERT 문을 하나로 결합할 수 없습니다.

어떤 사람들은 왜 독트린이 다중 삽입어(...), (...), (...), (...), (...), (...), (...)를 사용하지 않는지 궁금해하는 것 같습니다.

우선, 이 구문은 mysql 및 새로운 postgresql 버전에서만 지원됩니다.둘째, AUTO_INCRECTION이나 SERIAL을 사용할 때 이러한 다중 삽입에서 생성된 모든 식별자를 쉽게 파악할 수 없으며, ORM은 개체의 ID 관리를 위해 식별자를 필요로 합니다.마지막으로 삽입 성능이 ORM의 병목 현상이 되는 경우는 거의 없습니다.일반 삽입은 대부분의 상황에서 충분히 빠르며 빠른 대량 삽입을 원하는 경우 다중 삽입은 최선의 방법이 아닙니다. 즉, Postgres COPY나 Mysql LOAD DATA INFILE이 몇 배 더 빠릅니다.

이러한 이유로 인해 ORM에서 mysql 및 postgresql에 대해 다중 삽입을 수행하는 추상화를 구현할 가치가 없습니다.

Detrine2 배치 처리에 대한 자세한 내용은 여기에서 확인할 수 있습니다. https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html

DBAL로 전환하거나 설정된 삽입량 후 엔티티 관리자를 플러시하여 데이터를 소규모 배치로 처리할 수 있습니다.

$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();

이 포크는 https://github.com/stas29a/doctrine2 를 사용해 볼 수 있습니다.원하는 것을 정확히 구현해 줍니다.MySQL에서 테스트를 해보았는데 그 일괄 처리보다 5배 이상 빠르게 잘 작동합니다.이 포크는 첫 번째 삽입 ID를 얻고 다른 ID를 얻기 위해 php로 증가시킵니다.그것은 대부분의 경우에 효과가 있지만 전부는 아닙니다.따라서 이 포크를 사용할 때는 무엇을 하고 있는지 이해해야 합니다.

사용가능executeUpdate($query, array $params = array(), array $types = array())의 방법DriverConnection이 작업을 수행하기 위한 인터페이스.하지만 여러 개의 파라미터를 바인딩하는 것은 조금 어렵습니다.

데이터:

$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',
    ]
];

대량 업데이트 방법:

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
    );
}

감사합니다, 이제 교리를 통해서는 불가능하다는 것을 압니다.– @몰코베인

한방에 사용할 수 있습니다.

$em->merge($testCustomer);
그런 다음 플러시를 지속합니다.

작동할 것입니다.

테스트는 안 해봤는데 컬렉션으로 가능할 것 같습니다.

$collection = new Doctrine_Collection('tablename');
$collection->add($record1);
$collection->add($record2);
$collection->add($record3);
$collection->add($record4);
$collection->save();

물론 추가 기능이 있어야 합니다.

언급URL : https://stackoverflow.com/questions/18654530/doctrine2-multiple-insert-in-one-shot

반응형