Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Długi czas wykonywania skryptu, a optymalizacja bazy danych
Forum PHP.pl > Forum > PHP
klima06
Witam!
Obecnie piszę dość spory projekt, który będzie wykorzystywał CRON. Jeden skrypt musi być odpalany co 15 min, drugi raz dziennie o północy.
Mam dużą bazę danych MySQL i w jednej tabeli będzie się znajdować ok 20 000 rekordów. Skrypty te mają za zadanie przenieść wartość w każdym pojedynczym rekordzie z pola x na pole y. Zrobiłem to puszczając pętle przez wszystkie rekordy, ale czas wykonania skryptu trwa ponad 1-2 min (póki co serwer apache i mysql stoi na moim komputerze). Drugi skrypt zaś dla każdego rekordu musi zwiększyć wartość pola x o 15. Czy są jakieś specjalne zapytania mysql? Baza jest znormalizowana, posiada indexy. Zapytania w php również starałem się zrobić optymalne, czyli np. bez "SELECT * ..." tylko konkretne pola.
Jakie macie pomysły na jeszcze lepsze zoptymalizowanie tego wszystkiego?
ShadowD
Jak chodzi o zwiększenie danego pola o 15 to spróbuj tak:
UPDATE tabela SET kolumna=kolumna+15

Głupotą jest pobieranie całości powiększanie i znów zapisywanie do bazy, zapytania bez where lecą po całej bazie danych, podobnie pomyśl nad przeniesieniem pola, ale tutaj już Ci nie pomogę bo też nie jestem specjalistą od sql.
CuteOne
Najprostszy sposób to zwyczajne skopiowanie kolumn

  1. ALTER TABLE `table_name` DROP `new_test`;
  2. ALTER TABLE `table_name` ADD `new_test` TEXT NOT NULL;
  3. UPDATE `table_name` SET `new_test` = `old_test`;
klima06
Wielkie dzieki! Już zabieram się za przerabianie kodu.
Przeczytałem, że jeśli w danej tabeli często edytuje się dane to nie ma sensu robić indexów, czy to prawda? Jeśli wartości zmieniają się co 15 min, to często?

@edit
A w przypadku gdy muszę dodać 1000 rekordów na raz, to zamiast każdy dodawać oddzielnym zapytaniem, optymalniej będzie najpierw zapisać te rekordy do Arraya w PHP, a potem wszystkie dodać jednym zapytaniem w postaci:
Kod
INSERT INTO tabela (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
ShadowD
Jeśli ostatni akapit był pytaniem to odpowiadam - pewnie że tak, najwięcej czasu schodzi na wysyłania zapytań więc wszyscy ograniczają je do minimum, jak można pobrać 2-3 rzeczy za jednym razem po co pytać się servera o nie osobno?

Przykład z życia, siedzisz w pokoju (mysql) Twoja mama (php) biega z kuchni i co 2 minuty zadaje Ci pytanie, nie lepiej będzie gdy przyjdzie raz i zapyta na raz? ;->
klima06
Dobrze ale jeśli tabele mam znormalizowane i najpierw:
Do tabeli A dodaje wszystkie rekordy, każdy z tych rekordów dostaje automatycznie własne id.
Potem musze dodać wszystkie rekordy na raz do tabli B i C, w których muszą znajdować się id z wcześniej dodanych rekordów.
Jak to rozwiązać?
CuteOne
Do tego typu rzeczy polecał bym procedury + tzw. select update. Na googlu znajdziesz całą masę artykułów jak wykonywać "select update" za pomocą procedur smile.gif
klima06
Skonktowałem się z osobą, która ukończyła podobny projekt do mojego i dostałem parę rad, ale nie rozumiem ich w pełni. Niestety po angielsku. Rozumiem treść emaila i nie potrzebuję tłumaczenia, tylko potrzebuję objaśnienia jak to zrobić:
Kod
Well, you can multithread the fetching of the data. As far as getting them into the database, use an engine that caches not only the indexes, but the data itself in RAM. This however means you will need about 768MB of RAM DEDICATED to your MySQL server. You can also setup your queries to update multiple rows in one query (processing the query itself carries overhead, and you will be eliminating much of it), and you can also use "insert into - on duplicate key update" to save any double parses. From memory

Czy serwer musi być dedykowany? O co chodzi z tym zapisywaniem do pamieci RAM? i podwójnym parsowaniem?
viking
Zaczynając od podstaw konfigurowałeś serwer mysql? Ustawiłeś mu odpowiednie do posiadanego ramu i potrzeb parametry? Mysql ma również http://dev.mysql.com/doc/refman/5.1/en/mem...age-engine.html który mógłbyś spróbować wykorzystać. Na czas insertów możesz wyłączyć indeksy. 20k rekordów to według Ciebie dużo? Silnik powinien sobie z łatwością poradzić. Możesz też zainteresować się http://dev.mysql.com/doc/refman/5.0/en/cursors.html
klima06
Ale żeby przydzielić MYSQL RAM muszę posiadać serwer dedykowany? Na razie wszystko stoi na moim komputerze.
viking
Tak. Zależy gdzie chcesz to wrzucić. Jak administrator ma jakieś pojęcie o swojej pracy to będzie to działało nawet lepiej niż w domu u Ciebie. Zwłaszcza jak tam się jeszcze jakieś dyski SSD pojawią.
zegarek84
Cytat(klima06 @ 30.01.2012, 10:43:34 ) *
Potem musze dodać wszystkie rekordy na raz do tabli B i C, w których muszą znajdować się id z wcześniej dodanych rekordów.
Jak to rozwiązać?

połączenie zapytania:
INSERT INTO + SELECT - obczaj to ;] - przekopiujesz wymagane wiersze w jednej transakcji...
Cytat(klima06 @ 30.01.2012, 08:01:04 ) *
@edit
A w przypadku gdy muszę dodać 1000 rekordów na raz, to zamiast każdy dodawać oddzielnym zapytaniem, optymalniej będzie najpierw zapisać te rekordy do Arraya w PHP, a potem wszystkie dodać jednym zapytaniem w postaci:
Kod
INSERT INTO tabela (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

Poczytaj o transakcjach w bazie danych i tym podobnych rzeczach...
każdy taki insert domyślnie jest osobno commitowany (zatwierdzany) co też zabiera czas...
Przy technice o którą się pytasz z kolei będziesz musiał wszystko na raz wpakować do tablicy PHP, gdzie to w sumie nie jest konieczne. Możesz rozpocząć transakcję i puścić inserty w pętli po czym zatwierdzić transakcję... Dodatkowo jeśli korzystasz z PDO lub Mysqli możesz przygotować polecenie i potem w pętli to bindować i wykonywać w pętli bądź zbindować referencyjnie ze zmienną, i w pętli podmieniać jej wartość i wykonywać przygotowane zapytanie - taka technika tez jest szybka i nie musisz od razu wszystkiego do pamięci skryptu ładować...
klima06
Ogromne dzięki wszystkim, którzy wypowiedzieli się w tym temacie jednocześnie pomagając mi!

Serwer dedykowany jest za drogi jak dla mnie, patrząc że ten projekt jest 4fun. Jeśli miałbym postawić coś takiego na zwykłym serwerze wirtualnym, to który byście mi polecili ze względu na szybkość i pamięć przydzieloną dla MySQL?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.