netcoffee.pl*po godzinach - reaktywacja

Ten blog jest kontynuacją bloga dostępnego ongiś pod adresem netcoffee.pl/pogodzinach.
Artykuły, które na to zasługują są przenoszone do nowej wersji bloga. Pozostałe wkrótce znikną.

2005-10-30

Predkosc czy miejsce

Podczas pracy z MySQL, warto wiedziedziec o mozliwosci wplyniecia na wydajnosc bazy, juz na etapie projektowania jej struktury. W zaleznosci od zasobow ktorymi dysponujemy, mozemy zaprojektowac baze tak, aby dane w niej przechowywane zajmowaly jak najmniej miejsca, lub tak, aby wzrosla wydajnosc.

Model I - oszczedzamy miejsce
Podczas projektowania struktury bazy danych, wybieramy taki typ pol, aby zminimalizowac przestrzen dyskowa potrzebna do przechowywania danych. Jednym z typow pol pozwalajacych na oszczednosc miejsca jest VARCHAR. Rozmiar danych zapisanych w tym polu to L+1 bajtow, gdzie L to dlugosc danych zapisanych w kolumnie. Tak wiec 'string' zajmuje 6+1 = 7 bajtow (6 na zapisanie danych + 1 na oznaczenie konca danych).

Model II - zwiekszamy wydajnosc
Jezeli zastapimy pole typu VARCHAR (np. VARCHAR(30)) polem typu CHAR (tu: CHAR(30)), zwiekszy sie ilosc przestrzeni dyskowej potrzebnej na zapisanie danych. Pole typu CHAR zawsze zajmuje maksymalna ilosc przestrzeni dyskowej - tu 30 bajtow. Jezeli dane wstawione do takiego pola sa mniejsze niz 30 bajtow (np. 6), sa uzupelniane spacjami. To wyraznie zwieksza objetosc danych.

Jednak wykorzystanie modelu II niesie za soba znaczne zwiekszenie szybkosci wyszukiwania danych. Kazdy rekord zajmuje zawsze tyle samo miejsca, latwiej jest wiec wyszukac szukany rekord (aby odnalesc poczatek rekordu w pliku danych, wystarczy przemnozyc nr rekordu przez jego dlugosc). W przypadku modelu I nie jest to juz takie proste, gdyz wczesniejsze rekordy zajmuja rozna ilosc miejsca.

Podczas pracy z MySQL nalezy pamietac, ze rekord powinien zawierac wyszystkie pola typu CHAR (ogolnie: pola o stalej dlugosci) lub VARCHAR (oglonie: o zmiennej dlugosci). Jezeli tabela zawiera juz pole typu VARCHAR, to podczas dodawania pola CHAR zostanie ono dodane jako VARCHAR. Dlaczego? Otoz wstawienie pola CHAR nie zmieni formatu rekordu na staly gdyz istnieja w nim inne pola o zmiennej dlugosci. Nie niesie wiec za soba korzysci. Natomiast wstawienie pola VARCHAR zmniejszy ilosc potrzebnego miejsca. Dlatego podczas projektowania tabeli, nalezy wybrac odpowiadajacy nam model i konsekwentnie wybierac wymagane typy pol.

Niejednokrotnie jestesmy zmuszeni do umieszczenia w tabeli pola ktorego typ nie ma stalej dlugosci (np. TEXT) i nie mozemy uzyskac rekordu o stalej dlugosci. W takim przypadku warto rozwazyc przeniesienie pol o zmiennej dlugosci do innej tabeli (np. w przypadku forum, w jednej tabeli mozna przechowywac "metadane" wpisu - tytul, daty, id autora itd, a w drugiej sama tresc). Jednak takie rozwiazanie nalezy dobrze przemyslec w kontekscie projektu gdyz moze w rezultacie pogorszyc wydajnosc.

Inna wada Modelu I jest to co znamy z systemu plikow FAT - fragmentacja danych zapisywanych w pliku podczas edycji lub dodawania rekordow.
Uzycie Modelu II nie tylko nie powoduje fragmentacji danych, ale niesie za soba takze inne korzysci - prawdopodobienstwo naprawienia uszkodzonej tabeli jest o wiele wieksze, jezeli rekordy maja stala dlugosc.

Nie duplikuj informacji w bazie

Jedna z istotnych cech relacyjnych baz danych jest to, ze mozna przechowywane w nich informacje powiazac ze soba. Nie ma wiec koniecznosci duplikowania informacji zawartych w bazie.

Dla przykladu wezmy pod uwage system zawierajacy konta uzytkownikow, ktore mozna dowolnie przypisywac do grup. Istnieje takze mozliwosc wyslania wiadomosci e-mail do wybranej grupy.

Uproszczona struktura bazy danych to:
Tabela 'uzytkownik':
  • id
  • login
  • email
Tabela 'grupa':
  • id
  • nazwa

W bazie danych znajduje sie jeszcze jedna tabela - zawiera ona informacje o przynaleznosci poszczegolnych uzytkownikow do grup.
Blednie zaprojektowana tabela bedzie wygladac nastepujaco:
Tabela 'uzytkownik_grupa':
  • grupa_id
  • uzytkownik_id
  • email
W zalozeniu, aby pobrac adresy e-mail uzytkownikow nalezacych do grupy o id = 7, wystarczy wywolac zapytanie:
SELECT email FROM uzytkownik_grupa WHERE grupa_id = 7
Niestety, takie rozwiazanie ma powazne wady:
  • informacja o adresie e-mail uzytkownika jest zduplikowana - podczas jej uaktualniania, nalezy ja zmienic w dwoch tabelach
  • dane niepotrzebnie znajduja sie w drugiej tabeli - przez to zwieksza sie objetosc bazy danych

Rozwiazaniem probemu, jest zmiana struktury tabeli 'uzytkownik_grupa':
  • grupa_id
  • uzytkownik_id
oraz zmiana sposobu pobierania adresow e-mail:
SELECT u.email FROM uzytkownik as u, uzytkownik_grupa as ug WHERE u.id = ug.uzytkownik_id AND ug.grupa_id = 7

Takie rozwiazanie pozwala na redukcje ilosci zapytan do bazy danych w momencie aktualizacji adresu. Zapewnia takze, ze dane pobierane z bazy beda zawsze aktualne. Zmniejsza sie takze objetosc plikow z danymi w bazie - dzieki temu moze wzrosnac jej wydajnosc.

2005-06-04

Wyrażenia regularne - Jeffrey Friedl

Wyrażenia Regularne - okładkaWyrażenia regularne to bardzo potężne narzędzie - przydatne nie tylko programiście PHP ale także wielu innych języków. Obsługę WR znajdziemy w wielu językach (PHP, Perl, Java, Delphi, JavaScript), edytorach (Vim, Emacs, Html-Kit, Nisus Writer) i innych narzędziach (np. Total Commander).

WR pozwalają w prosty sposób sprawdzić format i poprawność wprowadzonych danych tekstowych, ale także wyszukiwać fragmenty tekstu. Na przykład, sprawdzenie poprawności podanego adresu bez wykorzystania WR wymagałoby conajmniej jednej pętli i instrukcji warunkowej. Dzięki WR, w PHP sprawa wygląda następująco:


<?php
if(preg_match('/^([a-z0-9_-]+)@([a-z]0-9\.)+([a-z-]{2,5})$/', $sEmail)){
echo 'Email OK';
}else{
echo 'Email błędny';
}
?>

Całość testu sprowadza się do użycia funkcji preg_match() sprawdzającej zgodność zawartości zmiennej $sEmail z wyrażeniem ^([a-z0-9_-]+)@([a-z]0-9\.)+([a-z]{2,5})$

Dodać także należy, że to sprawdzenie nie jest zbyt szczegółowe - sprowadza się jedynie do sprawdzenia, czy podany ciąg znaków zawiera znak @ (at), a przed nim znajduje się przynajmniej jedna litera (lub cyfra lub jeden ze znaków: - _) a za znakiem @ czy znajdują się grupy liter lub cyfr rozdzielone kropkami, przy czym ostatnia grupa może zawierać tylko 2 do 5 liter.

Nie będę teraz wyjaśniał znaczenia poszczególnych części tego wyrażenia. Dlaczego? Zagadnienie WR to temat nad wyraz obszerny - Jeffrey Friedl pisząc Wyrażenia Regularne (ang. Mastering Regular Expressions) potrzebował 320 stron aby opisać WR! I trzeba przyznać, że zrobił to wybitnie! Pozycja wydana nakładem wydawnictwa Helion, dostarcza gruntownej i szczegółowej wiedzy na temat wyrażeń regularnych. Co najważniejsze Friedl opisuje nie tylko składnię WR, ale także sam mechanizm, co znacznie ułatwia poznanie tego - jakże wygodnego - narzędzia.

Kolejnym bardzo istotnym atutem tej pozycji jest wybitny przekład oryginału, którego dokonał Adam Podstawczyński.