MongoDB. Baza zorientowana w okół dokumentów. NoSQL. Schema-free.

09:23, 15 listopada 2010 roku

| Opinie, Technologia

Próbując uruchomić Diasporę doznałem kilku olśnień. Głównym z nich było odkrycie MongoDB. Istnieje cała masa baz danych które powstały dzięki rozwojowi aplikacji WWW jak choćby “key->value store” używane przez Facebooka, a teraz prowadzone przez Apache pod nazwa Apache Cassandra Project. Mówiąc z perspektywy programisty WWW – bazy relacyjne nie wpasowują się w potrzeby moich aplikacji. Klientom dostarczam dokumenty, liczy się szybkość ich generowania. Rządzi XML. W końcu XHTML to jest XML. Dane są hierarchiczne i często ich struktury naturalnie są dynamiczne. Fajnie by więc było gdyby mogły w łatwy sposób być tak przechowywane. Tworzenie kilku tabel dla pięciu rekordów w bazie danych, gdy klient podał trzy numery telefonów zamiast jednego, jest olbrzymim (stosunkowo) narzutem pracy, logiki i skomplikowania. Ile razy widzieliście pola VARCHAR/TEXT w których dane były przechowywane po przecinku? No właśnie. Za dużo.

Dlatego wiele lat temu zakochałem się w PureXML serwowanym przez IBM DB2 od wersji 9.0 . A teraz porzucam moją starą miłość dla zupełnie nowej. Nie oszukujmy się, zmuszenie DB2 do działania według tego jak się chce, a nie jak baza chce, to jest katorga dla osoby która nie spędziła przynajmniej kilku miesięcy na kursach. Narzędzia do obsługi bazy są toporne i bolesne w użyciu. A narzut wiedzy który był mi potrzebny do wykonywania na niej operacji liczył około trzech tysięcy stron A4 (od instalacji, przez używanie do administracji). Nie chce nawet szacować ile czasu zajęło mi instalowanie tej bazy na serwerach i maszynie developerskiej za pierwszym razem.. drugim i kolejnymi trzema. Uczenie się DB2 przyniosło mi sporo wiedzy ogólnej, która przydaje mi się teraz od czasu do czasu, ale to nie jest godna rekompensata zużytego czasu.

Ale dość wstępu. W tym wpisie chcę się skupić na MongoDB, jako, że po kilku ładnych tygodniach testów różnych baz doszedłem do wniosku, że właśnie ten produkt najlepiej spełnia oczekiwania które mamy w Zeno.pl i te które można mieć przy pisaniu mocno obciążonych aplikacji. Z pewnością zbiorę się do napisania wniosków ogólnych dotyczących innych moich odkryć wyniesionych z Diaspory along the way. Ale póki co Mongo i jego NoSQL, Schema-free podejście do życia.

MongoDB

Baza oparta jest o JavaScript i JSON/BSON. Do wykonywania zapytań używa się składni JS i JSON, dane przechowywane są przy użyciu JSONa i BSONa (do danych binarnych). Próg wejścia jest więc znikomy dla każdego kto pisał jakąkolwiek interaktywna aplikację WWW. Jest to ogromny plus. Od instalacji do pierwszych zapytań minęło u mnie kilkanaście minut. Na stronie jest ciekawie zrobiony interaktywny tutorial, dokumentacja jest tworzona na bieżąco i można o niej powiedzieć, że jest kompletna.

Sama instalacja bazy jest prościutka – wystarczy swoim managerem paczek zassać i zainstalować bazę i klienta. Standardowa konfiguracja wystarcza do zabawy i testów. Sterowniki do PHP dostępne są z poziomu PECLa

sudo pecl install mongo

Na stronie podręcznika do PHP dostępny jest opis klas tego sterownika.

Baza jest w stu procentach dynamiczna.

Ma to swoje plusy i minusy. Bazy danych i kolekcje (odpowiedniki tabel) tworzone są dynamicznie – oznacza to, że baza nie krzyczy na nas za literówki. Jeżeli raz napiszemy

db.users.insert({"name": "Zenobius" });

(komenda wstawiająca dokument – odpowiednik rekordu – do kolekcji user z polem – kolumną - name która ma wartość “Zenobius”) to Mongo sprawdzi czy w używanej przez nas bazie jest już kolekcja users, jeżeli nie to ją utworzy. Gdy za drugim razem wpiszemy

db.usrs.find();

(komenda listująca wszystkie dokumenty z kolekcji usrs ) to Mongo nie nakrzyczy na nas, tylko wyświetli pusty zbiór wyników. Gdy wpiszemy

db.usrs.insert( {"name": "Zenobius" } );

to Mongo stworzy kolekcję usrs, wstawi do niej dokument z polem name o wartości Zenobius i będzie się cieszyć z dobrze wykonanego zadania.

Co ciekawe każdy dokument przy insercie dostaje generowany przez bazę identyfikator. Dotyczy to też sterowników do PHP – po wywołaniu inserta obiekt który dodawaliśmy dostaje automatycznie pole _id .

Kolekcje tworzone są dynamicznie. Jestem w stanie wyobrazić sobie godziny spędzone na szukaniu buga polegającego na zjedzeniu literki. Z drugiej strony nazwy kolekcji i baz danych powinny być trzymane w modelu lub pliku konfiguracyjnym i nie zmieniane – więc da się z tym żyć.

Aby stworzyć bazę danych wystarczy użyć polecenia

use <nazwa bazy>

i baza jest gotowa do użycia. Domyślnie przy użyciu wiersza poleceń ( mongo ) używana jest baza test .

Baza jest skalowalna horyzontalnie. Jest to niesamowicie proste do skonfigurowania – wystarczy kilka poleceń na poziomie roota i admina bazy.

Replikacja danych, podobnie jak skalowanie, jest bardzo łatwa do skonfigurowania. Bazę można z łatwością dostosować do swoich potrzeb. Można wymusić zapis na kilku serwerach. Z łatwością w trybie produkcyjnym można przełączać status master i slave, aby zrobić np. backup danych.

Używa UTF8 – tak jak powinien to robić każdy z nas.

Support i interakcja twórców ze społecznością i developerami jest świetna. Przykładem może być współpraca twórców MongoDB po wpadce foursquare opisana na łamach high scalability. Oczywiście twórcy bazy nie mogli sobie pozwolić na zły PR, ale poziom szczegółowości, otwartość i szybkość reakcji sprawiają, że jestem pod wrażeniem.

MongoDB Admin UI

Do MySQLa mamy phpMyAdmina, do Postgresa mamy pgAdmina, do DB2 jest DB2 Developer Workbench. Dla Mongo też jest kilka interfejsów. Ich opis, po angielsku, dostępny jest na blogu Tima, oraz na stronie MongoDB.

Osobiście używałem póki co tylko ob PHPowych, z których o wiele lepszy jest Opricot. Ale jeżeli ktoś z was ma ochotę pobawić się Pythonem lub Ruby i dać znać czy warto – to czekam na komentarze.

Na koniec jeszcze mały cheat-sheet SQL <-> Mongo.

Aplikacje Webowe muszą być dynamiczne. Musimy mieć też możliwość szybkiego wprowadzania w nich zmian aby wyprzedzać konkurencję. Próg wejścia dla Mongo jest niski – wystarczy kilka dni nauki i poruszamy się w jego środowisku swobodnie. Natomiast zyski z użycia Mongo wydają się być spore, jeżeli nie ogromne. Łatwość użycia, szybkość działania, łatwość konfiguracji replikacji i skalowania, prosta składnia – to wszystko rozwiązuje wiele problemów czy pytań które pojawiają się gdy używamy MySQLa czy Postgresa. Dynamiczna struktura dokumentów pozwala z łatwością zapisać w tej bazie wszystko. Fakt, że opiera się na JSON pozwala na bardzo łatwą manipulację danymi z poziomu PHP. Minusem jest mała dostępność bazy na hostingach i potrzeba migracji danych ze starej bazy i przepisanie całego modelu aplikacji. Natomiast jeżeli zaczynamy pisać coś zupełnie nowego to radzę poważnie zastanowić się nad MongoDB.


Napisane przez Zenobius | Komentarzy (0) | Permalink

DB2 V9.x i PHP – co mi da ich mariaż?

02:10, 19 czerwca 2010 roku

| Notka, Opinie, Praca

Dobrych kilka lat temu usłyszałem o powstaniu hybrydowych baz danych. Hybrydowe w poprzednim zdaniu oznacza łączące silniki relacyjne z hierarchicznymi. Z moich informacji, z tego co wiem, wynika, że póki co połączenie XMLa (bo to zazwyczaj jest implementacją hierarchiczności) z relacyjnością zostało dodane w takich bazach jak Oracle czy IBM DB2.

Od tamtego czasu sporo się w bazach namieszało, Oracle przejęło MySQLa, Facebook zrobił własną bazę danych, która aktualnie jest pod opieką fundacji Apache i zwie się Cassandra (zresztą, to co zrobił Facebook z PHPem zasługuje na osobny wpis). Przyszłość bazowa może być bardzo ciekawa :-)

Ale skupmy się na temacie mariażu DB2 z PHP.

Po co?

XHTML to XML. Ten prosty fakt sprowadza się do tego, że możemy zapisywać gotowe kawałki kodu XML w bazie danych w polach XML – wyciągać odpowiednie kawałki, składać ze sobą i “wypluwać” stronę. Proste, ale od czegoś trzeba zacząć.

XML nadaje się świetnie do składowania różnych płynnych danych – jako, że nie narzuca nam z góry formy w której musimy je przechowywać (możemy sami sobie je narzucić poprzez DTD lub XML Schema). W przypadku chęci posiadania wielu adresów klienta, czy wielu numerów telefonu jednej osoby – XML jest lepszą alternatywą, niż tworzenie kolejnej tabeli tylko na któreś z tych danych. PHP jest biedne (miejmy nadzieję, że “jeszcze biedne” a nie “na zawsze biedne”) jeżeli chodzi o modyfikację XML. Jedynym sposobem sensownej modyfikacji jest DOM, który jest o wiele bardziej nieprzyjemny w użyciu niż SimpleXML. Coś za coś, możliwe, ze udostępnię w jakimś czasie klasy do modyfikacji PHP pozwalające na dowolną modyfikację XMLa z łatwością SimpleXMLa.

XML w połączeniu z XSLT może robić za świetną warstwę danych i wizualizacji. Przy pomocy XSLT możemy przetworzyć dowolny plik XML do.. dowolnego innego formatu opartego na tekście. W naszym kontekście oznacza to możliwość przeniesienia warstwy widoku na klienta. Do klienta wysyła się plik XML z danymi (za każdym razem w odpowiedni sposób zmodyfikowany – aby odzwierciedlić dane które są aktualne), oraz szablon XSLT który parsuje XML do XHTMLa i pokazuje użytkownikowi za pomocą przeglądarki. To jest dość ciężki punkt, gdyż trudno w XSLT tworzyć dynamiczne linki (składać atrybut node’a XMLowego z kilku wartości). Ale przy odpowiednim przetworzeniu XMLa po stronie PHP, żeby lepiej nadawał się do parsowania przez XSLT – jest to do zrobienia.

Pierwsze dwa punkty były dość trywialne. Ot, kolejna opcja do rozwiązania dość popularnego problemu. Mająca swoje minusy i plusy – wybrać można co się chce.

Trzeci punkt to zupełnie nowe (a może już nie takie nowe i ktoś już tak robi?) podejście do parsowania stron i pokazywania ich klientowi. Parsowanie szablonu i upychanie do niego odpowiednich danych to jest ból i dla serwera i dla ludzi którzy muszą uczyć się specyficznego, użytego w naszym projekcie, języka szablonów.

Tak naprawdę XSLT jest, znów, kolejnym językiem do nauczenia.. ale w odróżnieniu od Smarty czy OPT spełnia więcej niż jedną funkcję i można go zastosować do dowolnej transformacji dowolnego pliku XML – ma to swoje plusy.

Co do serwera to zostaje on odciążony od tego – klient dostaje XML i XSTL i to jego przeglądarka zajmuje się przetworzeniem szablonu i wrzuceniu w niego danych – to jest piękne. Oczywiście to serwer może przetwarzać XMLa do XSLT przy użyciu np. XSL i klient dostaje już gotowego XHTMLa (ale skrótów, uff :-) ). Np. jeżeli nie chcemy udostępniać użytkownikowi XMLa z danymi.

Przy użyciu jednego zestawu danych XML możemy dostarczyć stronę na wiele platform przy użyciu różnych szablonów XSLT.

Wszystko to co powyżej opisałem da się zrobić przy użyciu DB2 w połączeniu z PHP.

Mam wrażenie, że nie wszystko zostało tu napisane, więc temat będę jeszcze rozwijał. Postaram się też opublikować kod implementujący te rozwiązania. Opis instalacji DB2 na Linuxie i połączenie z PHP znajdziecie na moim blogu parę postów niżej.


Napisane przez Zenobius | Komentarzy (2) | Permalink

Instalacja DB2 na Linux’ie. Łączenie DB2 z PHP.

23:11, 28 lutego 2010 roku

| Notka, Tutorial

Edit: dodałem tekst o tym co może wyniknąć z połączenia DB2 z PHP.

O tym, czemu w temacie tej notki DB2 i PHP występują w jednym zdaniu, będzie gdzie indziej. A zapewniam, że temat jest interesujący. Poniżej opis jak zainstalować DB2 na serwerze z Linuxem ( testowaliśmy to na systemach: Fedora, CentOS, RedHat, Ubuntu ). Większość tego tutoriala została najpierw przetestowana przez Kamila, mi udało się rozwiązać kluczowy problem. Ale.. po kolei.

Ten poradnik jest też dla tych, którym po instalacji DB2 i sterowników pod PHP wyskakują błędy połączenia z bazą mimo, że wszystko poszło jak trzeba (patrzcie na punkt ostatni)!

Jaki Linux?

Po pierwsze, musimy zdecydować się na jakąś dystrybucję. DB2, jako, że jest produktem IBM’a, lubi się z RedHat’em (czyli z Fedorą i CentOS’em również) oraz SuSE. Kamilowi udało się to wszystko zrobić na Ubuntu. Myślę, że i inne dystrybucje dadzą sobie radę.

Ja osobiście używam Windowsa ( tak, Windowsa ) jako środowiska do pisania kodu, natomiast Linux’a postawionego mam na SUN’owskim VirtualBox‘ie. Do plików na nim dostaje się przez Sambę. Dzięki temu PDT myśli, że pracuje na Windzie, a ja odpalam wszystko na Linuxie. Jak się komuś spodoba taki sposób, to napiszę kiedyś jak to sobie ustawić wszystko.

Ale.. nie chce wywoływać burzy Win vs. Linux, czy dystrybucja A vs. dystrybucja B, więc na tym co powyżej poprzestanę.

Czego mi potrzeba?

Na pewno wspomnianego już Linux’a ;-) Poza tym trzeba ściągnąć DB2 w wersji Express-C (testowaliśmy z wersją 9.5 jak i 9.7 ), chyba, że ktoś ma licencje na pełną wersję DB2. Ale nie sądzę, żeby wtedy wchodził na mojego bloga ;-)

Jako, że na końcu tego tutoriala mamy mieć możliwość podłączenia się do DB2 za pomocą PHP – to przyda się mieć Apache’a oraz PHP ( my używaliśmy do tego 5.3.1 ). My zaczynaliśmy od czystego, ale myślę, że nie będzie problemów z “brudnym”.

Przy instalacji DB2 przez setup graficzny trzeba mieć zainstalowaną Java’e. Sposób wytestowany jest zarówno graficznie jak i z linii poleceń, aczkolwiek druga opcja oznacza więcej ręcznego babrania się w konfiguracji. W przypadku serwerowych systemów trudno o jakiegoś managera okien, jeżeli bawimy się na Linux’owym desktopie – to droga wolna.

Aby skompilować DB2 oraz drivery do połączenia z PHP potrzebny jest.. kompilator ( d-oh! ). Wypada więc zainstalować gcc .

Instalacja DB2

Ja omówię instalacje z linii poleceń. Kamil pewnie wrzuci na swojego bloga informacje o instalacji graficznej. Chociaż ona zazwyczaj polega na czytaniu tego co na ekranie i umiejętnym klikaniu “next” ;-)

Z linii poleceń

Ściągamy plik, rozpakowujemy, wchodzimy do katalogu który powstał, potem od katalogu expc no i zaczyna się zabawa..

1. Uruchamiamy:
./db_install
2. Wybieramy katalog instalacji ( domyślnie jest to /opt/ibm/db2/V9.[x]), katalog trzeba zapamiętać! ( x to wersja DB2 którą się instaluje ).

3. Wpisujemy “EXP” i pacamy “enter”

4. Instalacja robi swoje, idziemy po herbatę/kawę/colę/lub-gdzie-chcemy ;-)

5. Jeżeli wróciliśmy i na ekranie znaleźliśmy błąd w stylu
ERROR:
The following library files could not be loaded by db2langdir
in /tmp/exp/disk1/db2/linux/install/../bin

libstdc++.so.5
libstdc++.so.5
to oznacza to iż brakuje nam niektórych bibliotek C++ i musimy zrobić coś takiego
yum install compat-libstdc++-33
Po czym wracamy do pkt. 1 .

6. Przechodzimy do konfiguracji serwera po instalacji ręcznej. Opis tego procesu, po polsku, znajduje się w InfoCenter IBM’a.

Parę wskazówek, sugestii i rzeczy pomocnych do pkt 6. :

1) nie bawcie się w zmienianie domyślnych, sugerowanych tam rzeczy, jeżeli nie wiecie co robicie. DB2 w wielu miejscach ma różne ustawienia, które również trzeba wtedy zmienić. Czasem trudno do tego dojść. Jeżeli zdecydujecie się na wprowadzenie DB2 na produkcyjny serwer – wtedy poświęćcie czas na dokładniejszą naukę i zrozumienie zasad działania DB2.

2) w podpunkcie 3cim, jako typ uwierzytelniania, wybieramy “server”. Jest to najpopularniejsza metoda uwierzytelniania do której jesteśmy przyzwyczajeni. Jako login/hasło do bazy podajemy wtedy usera którego stworzyliśmy w podpunkcie 1szym. Czyli domyślnie db2inst1 i hasło takie jakie utworzyliśmy. Jak wyżej – nie kombinujcie z tym, chyba, że wiecie co robicie :-)

3) konfiguracja komunikacji DB2. W podpunkcie 3cim wpisujemy tą komendę
update database manager configuration using svcename serwer1|3100
razem ze znakiem |. Oczywiście biorąc pod uwagę swoją nazwę usługi, port itp.

Instalacja DB2 to, aktualnie, prościzna. Jeżeli trzymamy się instrukcji i czytamy to co “mówi” nam system – to jesteśmy w domu. “Tricky” jest kolejny punkt..

Instalacja driverów do DB2 dla PHP

Do połączenia się z DB2 potrzebujemy jakichś driverów. My używamy PDO_IBM. Dostępny jest także ibm_db2 który bardziej przypomina zestaw funkcji do MySQL’a, więc nie bierzemy go nawet pod uwagę (OOP ftw ;-) ).

Bardzo ważne jest aby zainstalować PDO_IBM w wersji 1.2.5 . Wersje wyższe (podczas pisania tego tekstu dostępne są 1.3.0 i 1.3.1) powodują sporo błędów przy wykonywaniu zapytań.

Kolejną sprawą jest to, że Fedora uparcie twierdzi, że PDO jest zainstalowane gdy próbujemy je zainstalować poprzez PECL’a. Natomiast gdy próbujemy zainstalować PDO_IBM to twierdzi, że PDO nie widział na serwerze. Tworzy to pewien impas. Jedynym sposobem na przełamanie owego jest ręczna kompilacja sterowników. A oto jak sprawić, by PHP miało PDO oraz PDO_IBM :
pecl download PDO_IBM-1.2.5
tar -xzf PDO_IBM-1.2.5.tgz
cd PDO_IBM-1.2.5
phpize

Jeżeli nie mamy phpize, trzeba sobie zainstalować paczkę php-devel poprzez
yum install php-devel.i686
Teraz czas na zapamiętany wyżej katalog, w którym zostało zainstalowane DB2. Należy go wstawić w miejsce mojego /opt/ibm/db2/V9.5/ .
./configure --with-pdo-ibm=/opt/ibm/db2/V9.5/
make
make install

W tym momencie plik pdo_ibm.so znajduje się w katalogu z extensions do PHP. Teraz należy dodać extension=pdo_ibm.so . W ulubionym edytorze stwórz sobie plik pdo_ibm.ini w katalogu /etc/php.d/ i wpisz tam extension=pdo_ibm.so .

Teraz resecik apache’a i..
php -m
Jeżeli nie ma błędu, a na liście pojawia się pdo_ibm – to jesteśmy w domu :-)

Tworzenie bazy danych w DB2

W necie jest dobry “survival guide” dla DB2. Jako, że jest to baza danych z długą historią życiową ma sporo naleciałości niezrozumiałych dla ludzi którzy nigdy nie mieli nic wspólnego z bazą danych tego typu. Jednym z przykładów na “wtf?” jest długość nazwy bazy danych. Otóż maksymalna długość nazwy bazy danych to 8 znaków.

Podobną śmiesznością jest “escapowanie” stringów. Otóż żeby “uciec” znak ‘ należy go poprzedzić drugim ‘. Czyli np.
SELECT ... WHERE name = 'Don''t be stupid!';
Żeby dostać się do linii poleceń db2, zakładając, ze właściciel instancji nazywa się db2inst1 klepiemy:
su db2inst1
db2

W linii poleceń db2 klepiemy:
create database test
I mamy już bazę danych ;-)

Tworzenie bazy danych DB2 nie uwzględniającej wielkości znaków przy sortowaniu ( do czego przyzwyczaja nas każda inna baza w standardzie )

W DB2 9.7 lub wyższej możemy sprawić, aby silnik nie uwzględniał wielkości liter przy sortowaniu. Aby tak się stało musimy stworzyć bazę z odpowiednim “collate”
CREATE DATABASE test
USING CODESET UTF-8 TERRITORY PL
COLLATE USING UCA500R1_LEN_S2


Ważna sprawa! Nie można zmienić “collate” później. Więc stosujcie to domyślnie przy tworzeniu bazy danych. Pomysł zgapiono z oficjalnego poradnika IBMa dotyczącego DB2.

Problem z kodowaniem znaków do UTF8

Jeszcze jeden mały “pro tip” który może się przydać, żebyście nie musieli przechodzić przez to co ja. Aby klient zwracał do PHP dane z odpowiednim kodowaniem UTF8 trzeba przelogować się na usera db2inst1 ( su db2inst1 ) i odpalić komendę
db2set db2codepage=1208
Miłej zabawy ;-)

A o pytania, instrukcje i sugestie proszę uderzać w komentarze. Nie uważam się za guru Linux’a ani za guru DB2 – to co tu opisałem to to do czego udało mi się dojść w ciągu ostatnich 3-4 lat obcowania z tą bazą w połączeniu z PHP.


Napisane przez Zenobius | Komentarzy (2) | Permalink