[MySQL] Jak =?ISO-8859-2?Q?zoptymalizowa=E6_te_operacje_=3F?=
sawic - 04-01-2007 14:10
[MySQL] Jak =?ISO-8859-2?Q?zoptymalizowa=E6_te_operacje_=3F?=
Witam. Podliczam parę rzeczy w bazie, wiem, że robię to w sposób bezsensowny (ale działa jak należy), ale nie wiem jak to zoptymalizować. Wklejam żywcem kod, może ktoś się pokusi o przeanalizowanie tego:
//stworz tymczasowa tablice $sql = "create temporary table db.tmpp(user char(20), wynik char(10), stawka int(3), profit float) ENGINE = MEMORY"; $result = mysql_query($sql) or die(mysql_error()); //zczytaj uzytkownikow (sa tylko unikalni, bo juz wczesniej robilem group by) $sql = "select user from db.statystyki where nowy = '1'"; $result = mysql_query($sql) or die(mysql_error()); //dla kazdego zczytaj 10 ostatnich wynikow i wpisz to do tabeli tymczasowej while ($line = mysql_fetch_array ($result)) { $sql2 = "insert into db.tmpp(user, wynik, stawka, profit) select user, wynik, stawka, profit from db.kupon where user = '". $line['user'] .."' and (koniec = '1' or (koniec = '0' and wynik = 'przegrany')) and data_dodania is not null order by data_wynik desc, data_dodania desc limit 10"; $result2 = mysql_query($sql2) or die(mysql_error()); } //dla kazdego uzytkownika podlicz jego 10 ostatnich wynikow $sql = "select round(((sum(profit) / sum(stawka)) * 100),0) as zysk, count(case when wynik = 'wygrany' then 1 else null end) as wygranych, count(case when wynik = 'zwrot' then 1 else null end) as zwrotow, count(case when wynik = 'przegrany' then 1 else null end) as przegranych, user from db.tmpp group by user"; $result = mysql_query($sql) or die(mysql_error()); //zapisz do glownej tabeli obliczone dane while ($line = mysql_fetch_array ($result)) { $sql2 = "update db.statystyki set zysk10 = '". $line['zysk'] ."', trafionych = '". $line['wygranych'] ."', zwrotow = '". $line['zwrotow'] .."', nietrafionych = '". $line['przegranych'] ."' where nowy = '1' and user = '". $line['user'] ."' limit 1"; $result2 = mysql_query($sql2) or die(mysql_error()); } //skasuj tymczasowa tablice $sql = "drop table db.tmpp"; $result = mysql_query($sql) or die(mysql_error());
Wszystko, co wcześniej kombinowałem rozłożyło te 'limit 10'. Muszę mieć 10 ostatnich wyników dla każdego, bez względu kiedy one były. Może ktoś by doradził coś, bo te obliczenia trwają strasznie długo :(
Pozdrawiam
Rafal \(sxat\) - 04-01-2007 14:10
> $sql = "create temporary table db.tmpp(user char(20), wynik char(10), > stawka int(3), profit float) ENGINE = MEMORY";
o ile chyba wiem to tabela temporary nigdzie nie jest zapisywana wiec po co engine=memory?
sawic - 05-01-2007 00:03
Rafal (sxat) napisał(a): > o ile chyba wiem to tabela temporary nigdzie nie jest zapisywana wiec po co > engine=memory?
Po to właśnie, że nie chcę nic zapisywać. Tylko wybrać parę rekordów, wykonać na nich obliczenia, obliczenia zapisać, rekordy skasować.
W uproszczeniu - mam w bazie wiele rekordów, każdy rekord ma date i użytkownika. Ja chcę wybrać 10 ostatnich dla każdego użytkownika i wykonać na nich obliczenia. Nie mam zielonego pojęcia jak to sprawniej wykonać, niż ten bezsens który napisałem powyżej.
Pozdrawiam
zarafiq@poczta.onet.pl - 05-01-2007 00:04
> W uproszczeniu - mam w bazie wiele rekordów, każdy rekord ma date i > użytkownika. Ja chcę wybrać 10 ostatnich dla każdego użytkownika i > wykonać na nich obliczenia. Nie mam zielonego pojęcia jak to sprawniej > wykonać, niż ten bezsens który napisałem powyżej.
Nie napisałeś jaka baza, jeśli Twoja wersja ma "stored procedures" to już samo przeniesienie tego na serwer powinno troche pomóc.
Pozdrawiam zarafiq
-- Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
sawic - 05-01-2007 00:04
zarafiq@poczta.onet.pl napisał(a): >> W uproszczeniu - mam w bazie wiele rekordów, każdy rekord ma date i >> użytkownika. Ja chcę wybrać 10 ostatnich dla każdego użytkownika i >> wykonać na nich obliczenia. Nie mam zielonego pojęcia jak to sprawniej >> wykonać, niż ten bezsens który napisałem powyżej. > > Nie napisałeś jaka baza, jeśli Twoja wersja ma "stored procedures" to > już samo przeniesienie tego na serwer powinno troche pomóc.
MySQL # Wersja serwera: 5.0.26-log # Wersja protokołu: 10 Typ tabel: MyISAM
strored procedure wg manuala jest.
Jak to ugryźć ?
Pozdrawiam
Artur Muszynski - 05-01-2007 00:04
=?iso-8859-2?Q?Re:_=5BMySQL=5D_Jak_zoptymalizowa=E6_te_operac je_=3F?=
sawic wrote: > Witam. > Podliczam parę rzeczy w bazie, wiem, że robię to w sposób bezsensowny > (ale działa jak należy), ale nie wiem jak to zoptymalizować. > Wklejam żywcem kod, może ktoś się pokusi o przeanalizowanie tego:
[...] ile jest tych userów? Tzn ile razy wykona zapytanie w pętli. Jeśli bardzo dużo, to może tak: Wybierz ostatni rekord (z pomocą agregacji MAX) dla wszystkich userów i zapisz do temp. Potem wybierz wcześniejszy i tak 10 razy (lepsza taka pętla niż 100 czy 1000). Żeby wybrać wcześniejszy trzeba by wykluczyć z wyników, te już wcześniej wybrane, na przykład robić złączenie statystyki z tabelą tymczasową. Nie mam czasu, żeby się bardziej w to wgłębiać, ale może uzyskasz dzięki temu inne spojrzenie na problem. Z typem memory nie musisz aż tak kombinować, przecież i tak tabela tymczasowa zostanie usunięta po zamknięciu połączenia.
artur
sawic - 05-01-2007 00:04
Artur Muszynski napisał(a): > ile jest tych userów? Tzn ile razy wykona zapytanie w pętli. Jeśli > bardzo dużo, to może tak: Wybierz ostatni rekord (z pomocą agregacji > MAX) dla wszystkich userów i zapisz do temp. Potem wybierz wcześniejszy > i tak 10 razy (lepsza taka pętla niż 100 czy 1000). Żeby wybrać > wcześniejszy trzeba by wykluczyć z wyników, te już wcześniej wybrane, na > przykład robić złączenie statystyki z tabelą tymczasową. Nie mam czasu, > żeby się bardziej w to wgłębiać, ale może uzyskasz dzięki temu inne > spojrzenie na problem. Z typem memory nie musisz aż tak kombinować, > przecież i tak tabela tymczasowa zostanie usunięta po zamknięciu > połączenia.
No pokombinuję. Userów jest około 500 a całość wykonuje się jakieś 5 sek. To dużo za dużo. Najwięcej czasu tracę na pętle while i połączenia do bazy. Chciałbym znaleźć rozwiązanie, żeby jak najwięcej operacji wykonać na bazie danych a jak najmniej na php.
Pozdrawiam
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
Gdzie MySQL 4.1, a gdzie 5.0?
[MS SQL] "set names" (mySQL) w MS SQL
oracle -> oracle lub oracle -> mysql replikacja - programy
[mysql 4.0] SELECT t1.id, t1.foo FROM t1 oraz COUNT t2 w jednym zapytaniu.
[MySQL] Zwrot tego, co pasuje i nie pasuje :-/
[pgsql] Dostosowanie składni MySQL 5.0 -> PGSQL 8.1
[mysql] galeria zdjec - numerowanie zdjec
[MySQL] Zapytanie z pliku , wynik do pliku
[mysql] CONCAT agregujący, ale nie GROUP_CONCAT()
mysql data 0000-00-00 na koniec
zanotowane.pldoc.pisz.plpdf.pisz.plred-hacjenda.opx.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 |
|