Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: szybkość działania dużych baz danych
Forum PHP.pl > Forum > Bazy danych > MySQL
hobibit
Nie wiem czy dobrze mi się wydaje czy gdzieś w kodzie może błąd popełniłem.
Zdaje się że duże bazy danych działają dużo, dużo wolniej.
Mam kawałek skryptu php który pobiera jeden rekord z bazy mysql.
Jeśli baza m jeden rekord wszystko idzie szybko (przykładowo jeden, może być że 100), kiedy ma natomiast 10 milionów idzie powolnie. Normalna sprawa, ma więcej rekordów do przejrzenia itp.
Czy jest jakiś sposób żeby działało to tak samo szybko przy dużych bazach albo przynajmniej nie strasznie wolno.
Cashowanie nie zadziała bo dan są cały czas zmieniane
Nie wiem czy LIMIT 1, zadziała tak ze po znalezieniu przestanie dalej szukać, ale to zadziała tylko gdy rekordy będą z 'przodu' bazy danych.
Czy są jakieś sposoby na to?
Może zmiana bazy danych na jakiąś inną, ale z innymi nie mam doświadczenia więc proszę o rade która dobrze się sprawdza z dużymi bazami danych.
maly_swd
1. struktura bazy
2. odpowiednie typy danych
3. odpowiednia dlugos pol
4. indexy
5. optymalne zapytanie

juz na wstepie widac ze 5 pkt nie przestrzegasz:)... Twoje pytanie o tym swiadczy.. skoro my nie wiemy o co pytasz "brak przykladu", to pomysl co ta biedna baza danych ma zrobic jak jej zadajesz podobne zapytanie jak tu na forum:D
hobibit
Baza jest zbudowana w miare dobrze, zapytania są dobrze sformułowane. Nie o to mi chodzi czy coś dobrze napisałem czy nie, i nie tak brzmiało pyranie. Stwórz sobie tablice w mysql-u która będzie miała 100 MB wielkości i sprubuj wyciągnąć z niej 1000 rekordów, zajmie to wieczność. Co zrobić żeby działało to szybciej? Nie chodzi konkretnie o jeden przykład ale o 'teorię'. Ktoś mi powiedział że bazy postgresql poradzą sobie z dużymi bazami danych. Nie wiem czy tak jest czy nie bo działałem tylko na bazach mysql, wiec jak jest naprawde, czy te postgresql bazy danych radzą sobie dobrze z dużymi bazami danych ?
wookieb
Cytat(hobibit @ 7.11.2009, 23:09:19 ) *
Stwórz sobie tablice w mysql-u która będzie miała 100 MB wielkości i sprubuj wyciągnąć z niej 1000 rekordów,

Tabelę. Spróbuj. Zajmie to 1/1000 sekundy. Test na bazie 400 MB ponad 800 tys rekordów, indeks na szukane pole i zapytanie typu LIKE '%a%' Wykonane w 0,00012 sekundy. Oczywiście przeanalizowanie takiej ilość rekordów przez skrypt jest dłuższe ale bardzo rzadko zdarza się sytuacje, że tyle rekordów potrzeba bardzo szybko "przetrzepać" przez skrypt.

Cytat(hobibit @ 7.11.2009, 23:09:19 ) *
Nie wiem czy tak jest czy nie bo działałem tylko na bazach mysql, wiec jak jest naprawde, czy te postgresql bazy danych radzą sobie dobrze z dużymi bazami danych ?

Tak. Lepiej sobie radzi z takimi bazami danych aczkolwiek nie pamiętam jak to jest dokładnie z prędkością. Mogło się dużo zmienić od ostatnich czasów. Powiedz co masz za bazę i co w niej trzymasz.
maly_swd
pokaz strukture tabeli/bazy oraz pokaz jakie zapytanie robisz.
U mnie na bazie okolo 15milionow rekordow wyszzukiwanie z JOINAMI trwa okolo 0,05-0,2sek

hobibit
Więc z pewnością gdzieś błąd zrobiłem ale za chiny nie wiem gdzie.
id int(8)
id_mapa int(3)
wnetrze_budynku int(2)
x int(5)
y int(5)
typ tinyint(2)
grafika varchar(5) latin1_swedish_ci
w_pn tinyint(1)
w_ws tinyint(1)
w_pd tinyint(1)
w_za tinyint(1)
surowiec tinyint(2)
surowiec_nazwa varchar(30) latin1_swedish_ci
surowiec_st tinyint(1)
surowiec_wsp1 varchar(15) latin1_swedish_ci
surowiec_wsp2 varchar(15) latin1_swedish_ci
surowiec_mod tinyint(3)
fabryka tinyint(2)
id_budynek int(6)
budynek_typ int(2)
budynek_gracz int(7)
budynek_grafika varchar(1) latin1_swedish_ci
id_gracz int(6)
grafika_gracz smallint(4)
front tinyint(1)
zwrot tinyint(1)
szerokosc tinyint(1)
dlugosc tinyint(1)
czas int(11)
obiekt_1 int(5)
obiekt_2 int(5)
obiekt_3 int(5)
obiekt_4 int(5)

Zapytanie php wygląda tak:
  1. $calaWidocznaMapa = mysql_query('SELECT x,y,id_gracz,grafika,grafika_gracz,zwrot,obiekt_1,obiekt_2,obiekt_3,obiekt_4 FROM mapa WHERE id_mapa="'.$pierwszePole['id_mapa'].'" AND x>="'.$X_min.'" AND x<="'.$X_max.'" AND y>="'.$Y_min.'" AND y<="'.$Y_max.'" ');


Z całego skryptu wszystkie pozostałe zapytania usunąłem, nic więcej praktycznie nie ma (1,2 ale małe).
Zawsze pobieram taką samą ilość rekordów, zawsze. Zawsze robie z nimi dokładnie to samo, ten sam skrypt.
Kiedy w tablicy jest 1000 rekordów wszystko śmiga, kiedy jest 1000000 żółwi się strasznie mimo że niby pokazuje za operacja zajmuje mu najwyżej sekunde.
thek
Zzacznij może od zmiany x> a AND x < b na Between dla x i y. id_mapa powinien mieć indeks i zastanawiałbym się nad tym czy te x, y też nie walnąć do indeksów.
wookieb
Pisałem, że przeanalizowanie takiej ilość rekordów (pobranie, wrzucenie do tablicy (broń boże do obiektu)) jest znacznie dłuższe. Widzę, że jest to skrypt mapy ale powiedz mi proszę dlaczego pobierasz aż tyle rekordów?
hobibit
Dane są następnie do tablicy wrzucane a potem wszystkie są drukowane, dlatego aż tyle.
Problem jest taki że ten sam skrypt działa szybko dość na małych bazach mimo że pobiera tyle samo rekordów i tak samo je przerabia a przy większej bazie się gubi.
nospor
no to ci napisano przeciez:
zaloz indexy na pola: x, y oraz id_mapa

Dodatakowo skoro to są liczby (x,y, id_mapa) to nie bierz ich w apostrofy. Liczba to liczba a nie tekst.
hobibit
Zrobiłem jak radziliście, działa faktycznie szybciej.
Ale cały czas widze że w bazie jest 1000 rekordów działa to 4 razy szybicej niż przy 2000000 rekordów. Sprawa jasna ale może macie jakieś inne pomysły na przyspieszenie działania.
nospor
no ale jakiego to są teraz rzędu czasy?
1000 - 0.001 s
2000000 - 0.004 s
?
No to naprawdę nie masz juz co sie martwic winksmiley.jpg
phpion
Cytat(nospor @ 9.11.2009, 12:21:13 ) *
zaloz indexy na pola: x, y oraz id_mapa

Wydaje mi się, że lepiej sprawdziłby się tutaj 1 indeks założony na te 3 kolumny (w kolejności: id_mapa, x, y). W zapytaniu kolega i tak wyciąga rekord właśnie po takim warunku i w takiej kolejności, a przynajmniej odpadłby narzut aktualizacji 3 indeksów po zmianie danych w bazie. Przy SELECT pewnie różnicy by nie było widać, ale przy INSERT/UPDATE/DELETE już chyba tak. Myślę, że warto spróbować.
Ges
Ja ze swojej strony polecam trochę bardziej rozbudowane koncepcje na duże bazy danych:

- cachowanie (nie jest to rozwiązanie na bazie danych, ale może znacznie przyspieszyć odczyt danych pobieranych z bazy, poprzez cachowanie odpowiedzi bazy) np:. memcache

- replikacje (dublowanie baz danych w celu zrównoleglenia zapytań do poszczególnych duplikatów)
W tym rozwiązaniu masz 1 serwer MASTER na którym robisz UPDATE i odpowiednią ilość SLAVE które służą do odczytu danych. Również pomaga w odczytywaniu, ale już na poziomie bazy. Przy dynamicznych danych i małym hit rate cache, może się przydać.

- do INSERTów do baz danych jedynie klaster może Ci pomóc. Ale to rozwiązanie raczej nie będzie Ci potrzebne...

Oczywiście wszystkie z moich propozycji należy rozważyć po tym jak zoptymalizujesz już strukture swojej bazy (indexy + tabele) i dalej będziesz miał problemy z wydajnością. Z tego co widzę w tym wątku dużo rzeczy można u Ciebie poprawić jeszcze na etapie 1 bazy.

SELECTy i opisy "U mnie na bazie okolo 15milionow rekordow wyszzukiwanie z JOINAMI trwa okolo 0,05-0,2sek" sprawdzają się w 100% w momencie gdy nie masz około 100 zapytań / sekunde spowodowanych ogromną ilością użytkowników.\

Może moja propozycja jest na wyrost, a może komuś sie przyda...
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.