Jaka strategia dla update'u kilkudziesięciu milionów rekordów wmysql'u?
tomjan@jay.au.poznan.pl - 13-11-2006 00:45
Jaka strategia dla update'u kilkudziesięciu milionów rekordów wmysql'u?
Witam grupowiczów
Ponieważ nie moge znaleźć gotowej recepty w żadnej z książek + w archiwum grupy + w googlach zdecydowałem się wkońcu napisać na grupę.
Załużmy że nasza przykładowa baza wygląda jak baza rodowod (patrz koniec tej wiadomości) w której znajduje się od kilku do kilkudziesięciu milionów rekordów. pola osobnik,ojciec,matka,data_ur są uzupełniane a następnie program w C/C++ pobiera te informacje i na ich podstawie oblicza wartości 'f' oraz 'c' dla każdego osobnika.
Pytanie brzmi Jaka jest strategia wprowadzenia dla tych milionów rekordów obliczonej wartości 'f' oraz 'c'???
Czy robić to z poziomu aplikacji? jeśli tak to jak? czy ktoś mógłby podać przykładowy kod na to. jak to zaimplementować w C + jak to supportować konfiguracją mysql'a?
A może zrzucać to do pliku tekstowego jako liste query'ow i wciągać przez mysqlowego klienta?
a może robiąc jakąś sztuczke 'insert' do jakiejś tymczasowej tabeli powiązanej referencja zamiast 'update'?
Ja prubóje robić to z poziomu aplikacji w następujący sposób :
Rodowod::iterator it; for (it=begin();it!=end();it++){ sprintf(query, "update rodowod set f=%f,c=%f where id ='%s'",(*this)[it->first]->f,(*this)[it->first]->c,(*this)[it->first]->id_str.c_str());
if(mysql_query(mysql,query)){ printf("%d ", mysql_errno(mysql)); } }
powiem szczerze że idzie to masakrycznie wolno, zaimplementowałem wskaźnik postępu i widze że co kilka tys. rekordów procedura update'u stoi w miejscu od minuty do kilku minut. Prawde mówiąc nie wiem jak wyśledzić co się dzieje w tym czasie. zwiększyłem w pliku my.cfg wartość dla zmiennej key_buffer do 3072M i nic
wyczytałem w archiwum formu + w googlach że najlepiej opóźnić wykonanie wielu zapytań i wykonywać je naraz w większych "paczkach". ładnie brzmi ale jak to zaimplementować ? na poziomie API C czy na poziomie SQL'a. nie moge znaleźć na to gotowca.
dziękuję za jakiekolwiek podpowiedzi, sugestie, linki.
tomasz
ps. zapomniałbym o danych technicznych: Debian + mysql-5.0.24a-Debian_9 + 64bit + 8G RAM + 2x AMD Opteron(tm) 2592.316MHz
CREATE TABLE rodowod( id int(11) UNSIGNED NOT NULL auto_increment, osobnik varchar(25) NOT NULL default '', ojciec varchar(25) NOT NULL default '', matka varchar(25) NOT NULL default '', f real, c real, data_ur DATE, PRIMARY KEY (id), INDEX (osobnik), INDEX (data_ur) )ENGINE=MyISAM;
-- Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
zarafiq@poczta.onet.pl - 13-11-2006 00:45
> Witam grupowiczów > > Ponieważ nie moge znaleźć gotowej recepty w żadnej z książek + w > archiwum grupy + w googlach zdecydowałem się wkońcu napisać na grupę.
MySQL'a znam dość powierzchownie, ale... Wersja 5 obsługuje już zdaje się STORED PROCEDURES, czy nie da się tego policzyć tam? Uniknąłbyś pompowania tych milionów rekordów do aplikacji, a następnie milionów updateów z aplikacji.
Pozdrawiam zarafiq
-- Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
tomjan@jay.au.poznan.pl - 13-11-2006 00:46
> MySQL'a znam dość powierzchownie, ale... > Wersja 5 obsługuje już zdaje się STORED PROCEDURES, czy nie da się > tego policzyć tam? Uniknąłbyś pompowania tych milionów rekordów > do aplikacji, a następnie milionów updateów z aplikacji.
kod aplikacji w C++ zamyka się w 1000 lini kodu. więc niby niewiele. ale jak to kod C++ wykorzystuje STL,szablony i parę algorytmicznych trików + rachunek macierzowy. więc te 1000 lini naprawde dużo robi.
pewnie dałoby radę ale... wole posłuchać o innych możliwych rozwiązaniach.
(Choćby zwykła rekurencja już jest trudna do zaimplementowania w postaci mysqlowej funkcji użytkwnika.)
dziękuję za odpowiedź
tomasz
-- Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
tomjan@jay.au.poznan.pl - 13-11-2006 00:46
> pewnie dałoby radę ale... wole posłuchać o innych możliwych rozwiązaniach.
ponieważ nikt z forum nie kwapi się do hardcore'owej odpowiedzi jestem zmuszony sam mozolnie przedzierać się przezten problem (I żeby nikt nie myślał że mam jakieś pretensje, wiem że taki 'lajf').
Zmieniłem implementacje z:
Rodowod::iterator it; for (it=begin();it!=end();it++){ sprintf(query, "update rodowod set f=%f,c=%f where id ='%s'",(*this)[it->first]->f,(*this)[it->first]->c,(*this)[it->first]->id_str.c_str()); mysql_query(mysql,query); }
na podaną w przykładzie http://dev.mysql.com/doc/refman/5.0/...-handling.html czyli w pseudokodzie:
mysql_stmt_init() mysql_stmt_prepare() /* set up input buffers for all 3 parameters */ bind[0].buffer_type= MYSQL_TYPE_DATE; mysql_stmt_bind_param() Rodowod::iterator it; for (it=begin();it!=end();it++){ mysql_stmt_execute() }
pomogło: czas update'u 7 milionów rekordów spadł ze 150 min do 120.
czy ktoś mógłby się wypowiedzieć czy to jest względnie dobry czas dla takiego zadania czy mam jeszcze szukać innych możliwości optymalizacji? może ktoś podobnie duże zadanie robi np. w pół godziny? jeśli tak to jak?
acha, procesor: model name : AMD Opteron(tm) Processor 252 stepping : 1 cpu MHz : 2592.316 cache size : 1024 KB
versja bazy: 5.0.24a-Debian_9
dziękuję za odpowiedź
tomasz
-- Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
zarafiq@poczta.onet.pl - 13-11-2006 00:46
> for (it=begin();it!=end();it++){ > mysql_stmt_execute() > }
Rozumiem że nie masz *dokładnie* tak.
> pomogło: > czas update'u 7 milionów rekordów spadł ze 150 min do 120.
Wychodzi blisko 1000 na sekundę. Niby nieźle ale czy można lepiej? Za mało mam danych żeby powiedzieć. Mógłbyś napisać procedurę, która aktualizuje parę tysięcy rekordów i sprawdzić ile jej to zajmuje - to mógłby być punkt odniesiena.
Pozdrawiam zarafiq
-- Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
[ms sql] =?ISO-8859-2?Q?wy=B6wietlenie_pierwszych_5_rekord?==?ISO-8859-2?Q?=F3w_z_zapytania_=3F_odpowiednik_ROWNUM_w_o?== ?ISO-8859-2?Q?raclu_dla_MS_SQL=27a?=
[MySQL] =?ISO-8859-2?Q?Wy=B6wietlenie_kolejnej_pozycji=2C_?==?ISO-8859-2?Q?jak=B1_mia=B3by_dany_rekord=2C_gdybym_czyta=B3 _?==?ISO-8859-2?Q?wg_konkretnych_kryteri=F3w=2E_Da_si=EA_=3F?=
Jak =?ISO-8859-2?Q?zamieni=E6_dwa_pola_jednej_kolumny_?==?ISO-8859-2?Q?w_dw=F3ch_rekordach_za_pomoc=B1_jednego_zapyt? ==?ISO-8859-2?Q?ania=3F?=
[mysql/php] jak =?ISO-8859-2?Q?zliczy=E6_ilo=B6=E6_unikalnyc?==?ISO-8859-2?Q?h_rekord=F3w_w_jednym_zapytaniu=3F?=
=?ISO-8859-2?Q?WY=B6wietlenie_rekord=F3w_pocz=B1wszy_od_?==?I SO-8859-2?Q?danej_litery=2E=2E=2E?=
=?iso-8859-2?Q?=5BMySQL=5D_Wy=B6wietlenie_wszystkich_rekordow _zawierajacy?==?iso-8859-2?Q?ch_duplikat_a__moze_inna_struktura_bazy_danych ?=
[pgsql] Akcja w =?iso-8859-2?b?emFsZb9ub7ZjaQ==?= od liczby zmienionych =?iso-8859-1?q?rekord=F3w?=
[postgresql] kilka =?ISO-8859-2?Q?rekord=F3w_subquery_jako_?==?ISO-8859-2?Q?string?=
[mysql] Wyszukanie =?ISO-8859-2?Q?rekord=F3w=28powiazane_tabel?==?ISO-8859-2?Q?e=29?=
[MySQL]: Dodanie zliczania =?ISO-8859-2?Q?rekord=F3w_do_rozb?==?ISO-8859-2?Q?udowanego_zapytania?=
zanotowane.pldoc.pisz.plpdf.pisz.plnawschodzie.xlx.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|