Tomasz Ducin

Tomasz Ducin System Designer &
Architect, Trainer

Temat: Doctrine_Collection::save - 1 zapytanie, wiele rekordów

Robię migrację sporej ilości danych. Pierwsza wersja była "po chamsku":
pobieram starą kolekcję -> foreach -> tworzę nowy obiekt -> save

Przy dużej liczbie rekordów przestało mi to rozwiązanie wystarczać :) Zacząłem kombinować, żeby nie było osobnego insert query dla każdego rekordu, bo to bez sensu, skoro bez bólu można SQLem zrobić jednego inserta i dodać wiele rekordów. Więc zrobiłem:
Doctrine_Collection -> dododawałem mu obiekty -> save()

i... niestety różnica jest z tego co wiem tylko taka, że opakowuje je w kontener, ale w dalszym ciągu jest osobne query dla każdego rekordu.

Czy ktoś zna jakiekolwiek rozwiązanie, aby - przy użyciu doctrine'a zrobić w jednym zapytaniu wiele insertów?
Przemysław Szczerbicki

Przemysław Szczerbicki Programista,
freelancer

Temat: Doctrine_Collection::save - 1 zapytanie, wiele rekordów

Nie chciałbym teraz herezji napisać, bo mogło mi się w głowie coś pomieszać. Ale chyba nie wszystkie bazy wspierają taki multiple insert. Jeśli nie pomyliłem faktów to w takim razie ORM nie powinien tego wspierać, chyba, że symulować to dla baz niewspierających. Ale poproszę jeszcze o korektę tego co napisałem.

konto usunięte

Temat: Doctrine_Collection::save - 1 zapytanie, wiele rekordów

Michał Płonka:
Łukasz Adamczewski:
przekazujesz do metody save (w pętli tyle ile trzeba obiektów tworzysz) referencje do tego połączenia i na końcu commitujesz

Stwierdzenie o braku multi-insertów opieram na tym:
http://www.doctrine-project.org/blog/doctrine2-batch-p...
Some people seem to be wondering why Doctrine does not use multi-inserts (insert into (...) values (...), (...), (...), ...

CIACH!

These are the reasons why it is not worth the effort to implement an abstraction that performs multi-inserts on mysql and postgresql in an ORM.

Osobiście nie zgadzam się z takim rozumowaniem. Napisałem sobie klasę do wykonywania multi-insertów z wykorzystaniem Doctrine i nie uważam, aby włożony "wysiłek poszedł na marne". Z 25000 zapytań zszedłem do niecałych 800, szybkość wrzucania danych również znacznie się zwiększyła. Moim zdaniem było warto.
Wojciech Sznapka

Wojciech Sznapka CTO @ STS Zakłady
Bukmacherskie

Temat: Doctrine_Collection::save - 1 zapytanie, wiele rekordów

Doctrine nie wspiera multi-insertów. Robienie większej migracji jest praktycznie niemożliwe, bo prędzej czy później odbijesz się o limit pamięci php'a (ja migrowałem 1,5 mln rekordów, doctrine nie dał rady :-)). Zależy z czego migrujesz, ja np. miałem wszystkie dane z mysql zrzucone do csv, można sobie to podzielić na kawałki (linuksowy split) i zrobić 2 skrypty, coś na wzór producenta i konsumenta. Główny skrypt odpala w pętli exec'iem skrypt, który migruje dane, ale dostaje powiedzmy 100tys rekordów. Wtedy jak robisz inserty przez PDO nie powinno być problemów.
L P

L P podskala.net

Temat: Doctrine_Collection::save - 1 zapytanie, wiele rekordów

Tomasz Ducin:
Robię migrację sporej ilości danych. Pierwsza wersja była "po chamsku":
pobieram starą kolekcję -> foreach -> tworzę nowy obiekt -> save

Przy dużej liczbie rekordów przestało mi to rozwiązanie wystarczać :) Zacząłem kombinować, żeby nie było osobnego insert query dla każdego rekordu, bo to bez sensu, skoro bez bólu można SQLem zrobić jednego inserta i dodać wiele rekordów. Więc zrobiłem:
Doctrine_Collection -> dododawałem mu obiekty -> save()

i... niestety różnica jest z tego co wiem tylko taka, że opakowuje je w kontener, ale w dalszym ciągu jest osobne query dla każdego rekordu.

Czy ktoś zna jakiekolwiek rozwiązanie, aby - przy użyciu doctrine'a zrobić w jednym zapytaniu wiele insertów?

W pętli jednego skryptu (głównego) można wczytywać z db record-by-record i przekazywać record-by-record do nowego procesu-skryptu z danymi w parametrach (zadniem drugiego skryptu będzie przetworzenie danych na Twoje potrzeby i zrobienie insertu do db). Ten sposób jest wolniejszy ale za to stabilny (brak problemów z pamięcią np.). Odrobina kombinacji - innym skryptem można uruchomić n-workerów (wczesniejszych skryptów głównych), które przetworzą n zbiorów recordów: 1 do 10000; 10001 do 20000; (n*10000)-9999) do (n * 10000)). To oczywiście ma sens, gdy pomijamy ważność index'u klucza głównego w db.

Pozdrawiam Tomku!

Następna dyskusja:

Zapytanie w Doctrine




Wyślij zaproszenie do