Cytat(nasty @ 10.07.2012, 13:14:29 )

Weźmy sobie jako prosty przykład bazę danych która ma dane o użytkownikach, podzieloną na kilka tabel: Użytkownik, Adresy użytkownika, Kupione produkty. Żeby takie coś zaprojektować w relacyjnej bazie danych muszę przechować dane mniej-więcej w takiej strukturze:
- Tabela "Użytkownik"
- Tabela "AdresyUżytkowników"
- Tabela "Produkty"
- Tabela "KupioneProdukty"
Teraz - jeśli wykonamy zapytanie: Zwróć mi wszystkie adresy użytkowników którzy kupili produkty o cenie wyższej niż 100zł. Co silnik bazy danych zrobi z takim zapytaniem?
1. Przeleci po całej tabeli "Produkty" i przefiltruje ją pod względem ceny i zwróci kolekcję produktów która ma kolumnę "Cena" > 100 zł.
2. Listę produktów z podzapytania numer 1, wykorzysta, żeby przelecieć po tabeli "KupioneProdukty" i będzie porównywać elementy kolumny "Identyfikator Produktu" i sprawdzać czy należy do zbioru szukanych danych następnie utworzy nową kolekcję i dla każdego pozytywnego wyniku porównania identyfikatorów produktu, wrzuci do tej kolekcji wartość kolumny "Identyfikator Użytkownika".
3. Kolekcję identyfikatorów użytkownika uzyskaną z podzapytania numer 2, wykorzysta aby przeskanować tabelę AdresyUżytkownika i będzie porównywać każdy wiersz tamtej tabeli i sprawdzać czy wartość kolumny identyfikator użytkownika należy do tego zbioru.
4. Utworzy nową kolekcję do której będzie wrzucać wszystkie wiersze które pomyślnie przejdą porównanie w kroku numer 3.
(faktyczny query plan jest ciut bardziej skomplikowany - to jest delikatne uproszczenie)
Ten mały tekst jest chyba najważniejszy tutaj. Można go poprawić w kilku miejscach i należy pamiętać, że mając sztywne typy danych jest o wiele łatwiej implementować i optymalizować przeszukiwania.
Cytat
Żeby zrealizować takie zapytanie, wszystkie wiersze wszystkich tych tabel muszą znajdować się w "zasięgu" tego silnika bazy danych - w zasięgu znaczy, że musi mieć szybki dostęp do wszystkich tych wartości - więc albo dysk albo RAM. Tak się dzieję, ponieważ takie zapytania wymagają scanu po wszystkich dostępnych danych. To nie skaluję się dobrze/łatwo jeśli mamy miliony sprzedanych produktów, miliony użytkowników i miliony adresów (jak np. Amazon.com czy podobnych rozmiarów bazy danych).
I tak i nie. Jeśli weźmiemy generalny przypadek to może być ciężko, ale nie zawsze są nam potrzebne wszystkie dane. Z drugiej strony NoSQL nie rozwiązuje tutaj żadnego problemu, którego nie rozwiązuje rdbms. Dodajmy, że w prawdziwych zastosowaniach jak właśnie Amazon nikt nie trzyma w jednym obiekcie/wierszu towaru i ceny. Historia cen, ceny specjalne i tak dalej. Tutaj algebra relacyjna i integralność danych to ogromne ułatwienie. I tu jest pytanie jak chcemy skalować. Bo może lepiej mieć wielomilionową tabelę z kilkoma numerami na wiersz, które można analizować a opis na stronę pobierać z zewnętrznej bazy - sql pozwala na coś takiego - bo w nosql musielibyśmy dzielić całe obiekty i w momencie gdy chcemy produkty za $50 to musimy odpytać n serwerów.
Cytat
Bazy danych NoSQL przechowałyby te dane w inny sposób, zależnie od rodzaju bazy NoSql (jest ich mnóstwo - t.j grafowe, klucz/wartosc, dokumentowa, drzewiasta/hierarchiczna, itd..) i np. przechowałaby:
Kod
Użytkownik:
[
"Imie" : "Jasio",
"Nazwisko": Kowalski"
"Adresy" : [ "15 Ulica, Miasto", "18 Ulica, Miasto" ],
"Kupione Produkty": [ "Nazwa Produktu 1", "Nazwa produktu 2", "Nazwa produktu 3" ]
]
W tak ułożonych danych, nie ma zależności pomiędzy różnymi zestawami danych, dlatego, nie muszą one być natychmiastowo dostępne do zwrócenia wyniku zapytania: Zwróć mi listę wszystkich produktów kupionych przez użytkownika o nazwisku "Kowalski". Koszt jaki płaci się przy takiej strukturze danych to mocno ograniczona elastyczność zapytań. Żeby zwrócić wartość zapytania z wyżej podanego przykładu: "Adresy użytkowników którzy kupili produkty > 100zł", musimy własnoręcznie wykonać te wszystkie kroki podzapytania.
Tak, mam nazwy produktów, ale już nie mam ścieżki do obrazka produktu. A jak dodamy ścieżki i ceny i aktualne rabaty to mamy ogromną nadmiarowość danych. A jak będe tutaj trzymał id produktu? Też, jak w rdbms, muszę odpytać drugą baze/tabelę, ale nie mam zagwarantowanej integralności danych. Jak anuluje zamówienie to usuwam id, ale jak zmienie cenę? W sekcji "Twój znajomy kupił też:" wyświetlę buty, ale żeby pobrać cenę muszę odpytać inną bazę. Żadnego zysku.
Cytat
Co to nam daję? Daje to możliwość łatwego skalowania. Jak przechowujemy niezależne dane, to możemy zaprogramować farmę serwerów load-balancerów w taki sposób: Jeśli będzie zapytanie o użytkownia i ten użytkownik będzie miał nazwisko zaczynające się na literkę "K", to przekieruj to zapytanie to farmy serwerów znajdującej się w tu i tu. Jeśli będzie zapytanie o użytkownika o nazwisku zaczynającego się na "M" to przekieruj do serwerowni gdzieś indziej. I w taki sposób można bardzo łatwo odciążyć serwery i znieść potrzebę dostępu do całego zestawu danych na raz. Daję stabilność i fault-tolerance. Jeśli panie nam serwer z użytkownikami na literkę "J" to nam padnie tylko mała część danych, zapytania o "K", "G", "F" dalej będą działać poprawnie i będą zwracać poprawne i pełne wyniki.
Problem jest w podziale danych na niezależne części. Technologie nie dają odpowiedzi na to a to nie jest trywialne zadanie. Jeśli jest zapytanie o przyjaciół Marcina, którzy są znajomymi Karola? NoSQL to nie jest żadna odpowiedź i musimy być świadomi co poświęcamy.
Cytat
Czego to nam nie daję? Nie daję nam elastyczności zapytań - możemy zadawać tylko takie zapytania do bazy danych jakie przewidzieliśmy podczas jej projektowania pod daną aplikację i pod dany przypadek (chyba, że chcemy, żeby nam zapytanie wykonywało się bardzo wolno). Nie daję nam łatwego sprawdzania konsystencji danych. Jasio Kowalski może mieć w swojej liście kupionych produktów produkt o nazwie "Nazwa produktu 2" który zmienił nazwę na "Nazwa Produktu 7". Żeby ten update odzwierciedlił się wszędzie, musimy ręcznie pozmieniać te wartości w zestawie użytkowników (przelecieć po zbiorze użytkowników i zobaczyć czy tam jest nasz szukany produkt i jeśli tak to zmienić jego nazwę).
Zależy od bazy. Ale zakładając, że dalej się trzymamy baz typu dokumentowego to powiem, że racja. Co więcej - w sqlu istnieją techniki, które taką prędkość nam dadzą. Zmaterializowane widoki pozwalają tworzyć szybkie zapytania o skomplikowane relacje.
Sharding pozwala tak samo skalować bazy.
Polimorfizm wielotabelaryczny pozwala modelować zmienność rekordów.
Cytat
NoSQL przydaję się zazwyczaj wtedy kiedy zwykła relacyjna baza danych nie wyrabia (powyżej kilka Terabyte).
Po raz kolejny dziwna estymacja. Rozmiar danych to jeden z wielu czynników.
Wiem, że to wygląda jakbym uważał, że sql to najlepsze co jest. Ale polecam mojego pierwszego posta w tym wątku - wymieniłem zalety baz nosql, których doświadczyłem sam w mojej pracy. Po prostu nie jestem zwolennikiem poglądu, że nosql jest odpowiedzią kompletną. To są rozwiązania budowane wokól jakieś (jednej!) idei lub bolączki rdbms.
Z drugiej strony data-mining dla rozwiązań nosql jeszcze raczkuje, więc spore możliwości pracy dla mnie.