Warning: file_get_contents(http://graph.facebook.com/http://youthcoders.net/it/dev-zone/1035-wydajnosc-bazy-danych-a-wydajnosc-plikow-tekstowych.html): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden in /var/www/old-yc/plugins/content/addthis.php on line 38
Wydajność bazy danych, a wydajność plików tekstowych |
Wpisany przez Tomasz Stasiak | |||
poniedziałek, 25 kwietnia 2011 15:58 | |||
W związku z dyskusją jaka się wywołała między mną, a yarpo w komentarzach pod moim artykułem dotyczącym logowania w PHP, skorzystałem z propozycji i zrobiłem kilka testów wydajnościowych porównujących szybkość działania bazy danych opartej na plikach i takiej opartej na MySQL. Stanowiska były następujące: ja twierdziłem, że pliki są szybsze, yarpo, że niekoniecznie. Testy zostały przeprowadzone na małej (275 userów) i dużej (27057 userów) porcji danych, z wykorzystaniem bazy MySQL oraz plików tekstowych; przy nich była brana pod uwagę szybkość dodawania oraz szybkość wyszukiwania. Parametry środowiska testowego (serwera):
Kody, które służyły do testów: Baza na plikach:
Baza danych:
Profiler: (tu podziękowania dla yarpo za klasę, bo nie chciało mi się samemu pisać :p)
Jak widać do obu baz byli dodawani użytkownicy o losowo generowanych nazwach i hasłach, a później wyszukiwany jakiś użytkownik, który niekoniecznie musiał istnieć. Oba kody spokojnie można by jeszcze zoptymalizować, ale więcej mówi raczej typowy przypadek. W żadnym z testów nie uwzględniłem czasu otwarcia połączenia/wybrania bazy czy otwarcia/include'a pliku, aby pokazać sam czas operacji na danych (BTW mam nieodparte wrażenie, że otwarcie połączenia i wybranie bazy jest bardziej czasochłonne od otwarcia pliku...). Baza danych znajdowała sie na tym samym serwerze, co skrypt (co widać po wpisaniu localhost w hoście bazy). Teoretycznie można by się pokusić o trochę bardziej realistyczny przypadek, czyli otwieranie/zamykanie za każdym razem pliku/połaczenia z bazą, aby zasymulować operacje wykonywane przez różnych użytkowników (bo od kiedy jeden uzytkownik wykonuje ponad 50 tysięcy operacji na bazie danych w jednym czasie? :>), ale nie jestem pewien, jak serwer by zareagował na takie obciążenie i wolę go nie przeciążać za bardzo. Wyniki z użyciem plików:
Wyniki z użyciem bazy danych:
Jak widać, im więcej rekordów tym większą wydajność (w stosunku do plików) oferuje baza danych. Na niewielkiej porcji danych pliki tekstowe są niewiele szybsze od bazy przy wyszukiwaniu, natomiast o wiele szybsze przy zapisie. Prawdę mówiąc zdziwiła mnie tak duża różnica prędkości zapisu między bazą danych a plikami. Spodziewałem sie, że te drugie będą szybsze, ale nie prawie 10 razy! Niestety pliki mają także swe wady - przy dużej ilości danych może nam po prostu zabraknąć pamięci, gdyż cała tablica z pliku tekstowego musi zostać wczytana do pamięci, a przy kilku(dziesięciu|set) tysiącach użytkowników te dane mogą sporo zajmować (przede wszystkim przy bardziej rozbudowanych strukturach, nie tylko uzytkownik/hasło). Dodatkową ciekawostką może być fakt, iż tabela bazy danych MySQL waży mniej niż plik tekstowy. Mam teraz wrażenie, że jakimś cudem udało mi się obalić dowód przez oczywistość :P W razie wszelkich sugestii śmiało pisać - postaram się wybronić ze swego stanowiska.
ps. początkowo to miał być zwykły komentarz, ale się "trochę" za bardzo rozrósł... ps2. prawie zapomniałem: paczka z kodem
//edit: Nowe testy: Tym razem porównanie między szybkością otwarcia połączenia, wybrania bazy i zamknięcia połączenia oraz między czasem otwarcia, zablokowania i zamknięcia pliku. Tym razem nie będę się aż tak rozpisywal, bo już sił brakuje - może później ;] Kod użyty do testowania:
Tym razem oba testy zostały umieszczone w jednym pliku. Jak widać, w obu przypadkach zostało wykonane 100.000 operacji. Wyniki (output skryptu) - najpierw baza danych, później pliki:
Trzeba przyznać, że wyniki testu są druzgoczące - o ile przy zapisie/odczycie z bazy/pliku różnice były co najwyżej rzędu wielkości, to w tym wypadku różnica to ponad dwa rzędy wielkości (0,9s dla pliku w porównaniu do 10,1s dla bazy). Chociaż, patrząc z drugiej strony - nikt normalny chyba nie otwiera połączenia z bazą danych 100k razy za jednym zamachem? :>
jeszcze tradycyjna paczka z kodem :)
|
Komentarze
Może cała seria takich testów? :)
Widzę, ze spodobała Ci się opcja optymalizacji kodu, aby działał jak najszybciej :)
Może więc zainteresuje Cię serwis:
http://pl.spoj.pl/problems/latwe/
Aby w PHP wczytywać dane z wejścia [odpowiednik cin z c++] należy:
Cytat:
źródło: http://php.net/manual/en/features.commandline.php
Miłej zabawy :)
BTW dodane nowe testy do artykułu
Jednak mając na uwadze możliwość rozwoju naszego systemu często lepiej jest od razu dać bd. Lub odpowiednio obudować plik txt (np. w klasę implementującą jakiś interfejs) aby późniejsza zmiana pozwalała na wprowadzenie klasy gdzie dane trzymane byłyby w bazie, a interfejs pozostałby taki sam :)
Pamiętaj, że czas pracy programisty jest często ważniejszy niż czas pracy komputera.
przy małej ilości danych odczyt z pliku jest szybszy (no dobra, w granicach błędu pomiarowego, ale jest ;]), natomiast przy wzroście ilości danych...
Cytat:
No, w sumie nie raz, bo to samo jest przy wszelkich zmianach dotyczących ustawień konta (choć masz rację, że występuje wiele razy mniej niż odczyt).
Zapis następuje raz: przy rejestracji. Odczyt wielokrotnie - przy każdej autentykacji [np. logowaniu].
Warto było jednak dodać:
1. czas połączenia, jako kolejny test :)
2. flock na pliki. Bez tego [miałem już takie przypadki] pliki potrafią się np. opróżnić, czego tu byśmy raczej nie chcieli :)
http://php.net/manual/en/function.flock.php
bardzo ciekawy artykuł! :)