Zagadnienia

1. Wprowadzenie

Bazą danych nazywa się utrwalony zbiór danych, opisujących pewien fragment rzeczywistości i przeznaczonych do wspólnego wykorzystania przez różne programy. Jest to chyba najpopularniejsze wykorzystanie komputerów w życiu codziennym.

Przykładowo, w bazie danych banku mogą być gromadzone informacje na temat klientów, ich rachunków i operacji na tych rachunkach. Będą tam także informacje o udzielanych kredytach i ich spłatach.

Dane w bazie danych są zorganizowane w specyficzny sposób, zgodnie z modelem danych. Powinny odzwierciedlać rzeczywistość w sposób z nią zgodny.

1.1. Systemy informacyjne

Komputery obecnie służą przede wszystkim do przechowywania informacji i zarządzania nią, a nie do szybkich obliczeń numerycznych. Duże projekty informatyczne używające baz danych to często najbardziej złożone przedsięwzięcia podejmowane przez firmy. Na przykład systemy informowania kierownictwa (MIS – Management Information Systems) mogą obejmować:

  • dane finansowe firmy;

  • wyniki badań rynku, materiały marketingowe;

  • informacje o aktualnych i potencjalnych klientach.

1.2. Zastosowania baz danych

Tradycyjne zastosowania baz danych obejmują tekie dziedziny jak:

  • Obsługa wpłat i wypłat w banku.

  • Rezerwacja biletów lotniczych.

  • Przeglądanie katalogu bibliotek UW w internecie.

  • Zakupy w supermarkecie.

  • Kartoteki pracowników (kadry i płace).

  • Księgowość

W miarę upowszechniania informatyki pojawiło się coraz więcej innych zastosowań, z zupełnie nowymi problemami:

  • Multimedialne bazy danych: obrazy, muzyka, filmy.

  • Geograficzne systemy informacyjne (Geographic Information Systems — GIS).

  • Systemy analizy danych (Online Analytical Processing — OLAP) wykorzystujące hurtownie danych.

  • Poszukiwanie prawidłowości w danych (Data mining).

  • Naukowe i medyczne bazy danych

  • Wyszukiwarki informacji: Google, Amazon itp.

Bazy danych charakteryzują się przy tym pewną specyfiką, wyróżniającą je wśród innych działów informatyki.

Do opisywania operacji na bazie danych używa się ograniczonych języków programowania — jest to chyba jedyna znacząca dziedzina, gdzie używa się w praktyce języków programowania o mocy słabszej niż maszyna Turinga.

Ale za to występują specyficzne problemy związane z

  • optymalizacją wykonania zapytań dla wielkich zbiorów danych;

  • synchronizacją wielu transakcji wykonywanych równocześnie

1.3. Model danych

Przed skonstruowaniem bazy danych powinniśmy zapoznać się ze strukturą informacji, które zamierzamy w niej przechowywać. Służą do tego modele danych, pozwalające opisać własności danych w sposób ścisły (często sformalizowany) z wykorzystaniem języka matematyki. Przykłady takich modeli to

  • relacje (odpowiadające tabelom) w modelu relacyjnym

  • drzewa lub grafy w modelach semistrukturalnych

Oprócz opisywania struktury danych model powinien także określać dozwolone operacje na danych oraz sposób nakładania ograniczeń (więzów) zapewniających poprawność bazy danych.

1.4. Przykład relacji

Przykładowa relacja może mieć postać następującej tabeli

Narty

model producent
Cool Minx Atomic
Jewel Cristal Salomon

1.5. Schemat bazy danych

Strukturę danych i powiązania między nimi opisuje się w schemacie bazy danych. Schemat relacji podaje nazwę relacji i listę jej atrybutów. Dodatkowo można podać typy atrybutów

Przykłady:

  • Narty(model,producent)

  • Narty(model:string,producent:string)

Schemat bazy danych obejmuje schematy wszystkich relacji zawartych w bazie danych. W ten sposób baza danych jest po prostu kolekcją relacji.

Popatrzmy na zalety relacji:

  • Bardzo prosty model

  • Często intuicyjnie (zwłaszcza wśród biurokratów ;-) pasuje do danych

  • Znane własności matematyczne

  • Stanowi podstawę języka SQL

Pora na przykład nieco większego schematu:

Narty(model, producent)
Wypożyczalnie(nazwa, adres, telefon)
Narciarze(nazwisko, adres, telefon)
Lubi(narciarz, narty)
Wypożycza(wypożyczalnia, narty, cena)
Korzysta(narciarz, wypożyczalnia)

Podkreśleniem zaznaczamy klucz: atrybut (czasem atrybuty) taki, że w żadnych dwóch wierszach tabeli nie może mieć takiej samej wartości

Klucz to szczególny przypadek ograniczenia (więzów), nakładanego na bazę danych aby zagwarantować pewne warunki poprawności.

1.6. Realizacja baz danych

Najprościej byłoby wczytać na początku całą bazę danych do pamięci operacyjnej. Niestety współczesne bazy danych często mają rozmiary przekraczające 100 GB, co raczej wyklucza taie podejście. Poza tym na systemach z 32-bitową przestrzenią adresową można byłoby bezpośrednio odwoływać się do 4 GB danych.

Ponadto wykluczyłoby to (lub co najmniej bardzo utrudniło) współbieżny dostęp do bazy danych. Niemniej w pewnych sytuacjach, dla małych specjalizowanych baz danych może to być czasem sensowna realizacja.

1.6.1. Realizacja na plikach

Kolejna możliwość to skorzystać z plików dyskowych. System plików Linuxa czy Macintosha to bardzo prosty rodzaj bazy danych. Dane przechowuje się na dysku w nazwanych kawałkach (plikach), nie posiadających żadnej wewnętrznej struktury.

Zalety to pozorna prostota zarządzania (cały mechanizm jest po prostu fragmentem systemu operacyjnego), wystarczy od czasu do czasu zachować kopię archiwalną dysku na CD.

Niestety są również wady. Co stanie się, gdy w trakcje wykonywania operacji na bazie danych nastąpi jakaś awaria (błąd dysku, zanik zasilania, niedozwolona operacja)?

Po naprawieniu zawartość plików zapewne będzie niespójna, zwłaszcza biorąc pod uwagę, że system nie zawsze zapisuje zmiany w plikach na dysku w takiej kolejności, w jakiej je wprowadzaliśmy. Często stosuje się tzw. opóźniony zapis, ponieważ pozwala to zwiększyć wydajność systemu.

1.6.2. Wady plików

To jednak dopiero początek kłopotów. Przyjrzyjmy się bliżej poniższemu scenariuszowi.

Załóżmy, że tabelę Narciarze zapisaliśmy w osobnym pliku, każdy wiersz w osobnej linii, rozdzielając pola na przykład znakiem pionowej kreski.

Pierwszy kłopot to modyfikacje

  • Jeśli próbujemy zmienić adres jednego z narciarzy, a nowy adres jest dłuższy niż stary, to zamażemy (być może częściowo) jego telefon.

  • A jeżeli jest dużo dłuższy, to może i następny wiersz.

  • Wniosek: trzeba zapamiętać całą resztę pliku i zapisać na nowo.

Jeśli natomiast nowy adres będzie krótszy niż stary, to z kolei powstanie ,,dziura” — fragment pliku nie zawierający żadnej użytecznej informacji.

Popatrzmy teraz na następującą sytuację. Co się stanie, gdy dwie osoby równocześnie spróbują wykonać taką operację modyfikacji?

  • Każda z nich zapamięta dotychczasową ,,resztę” pliku, a następnie obie zaczną wpisywać nową wartość.

  • Być może obie zmiany wykonają się poprawnie.

  • A być może jedna z nich zostanie utracona.

  • Najgorzej będzie, gdy wpisywane zmiany zostana przemieszane tak, że żadna z nich nie będzie poprawna.

1.6.3. Synchronizacja dostępu

Potrzebujemy więc jakiegoś mechanizmu synchronizacji. Najprościej byłoby użyć blokad:

  • Ten kto pierwszy zaczął modyfikować rezerwuje cały plik tylko dla siebie.

  • Pozostali muszą czekać aż skończy.

Jest to świetne rozwiązanie, gdy współbieżność jest niewielka (a najlepiej, gdy wcale jej nie ma ;-).

Słabo sprawdza się jednak w przypadku systemu rezerwacji biletów lotniczych, gdy kilkadziesiąt żądań napływa równocześnie.

1.6.4. Zalety realizacji w bazie danych

Skorzystanie ze specjalizowanego systemu zarządzania bazami danych (ang. DBMS od Data Base Management System) ma w tej sytuacji szereg zalet.

  • Abstrakcja od szczegółów fizycznej implementacji, niezależność programów od danych, zwłaszcza od sposobu ich przechowywania.

  • Komunikacja na poziomie modelu danych — relacji, z użyciem specjalizowanego języka dostępu do danych: najczęściej SQL.

  • Opis struktury bazy danych (schemat) także przechowywany w bazie jako tzw. relacje katalogowe stanowiące słownik bazy danych.

  • Zawarte w katalogu informacje opisujące strukturę bazy danych nazywa się metadanymi

1.7. SQL

Podstawowym językiem komunikacji z relacyjnymi bazami danych jest SQL. Zawiera on zarówno konstrukcje do definiowania schematu danych jak i do operowania na zawartości bazy. Popatrzmy na dwa przykłady:

  • Definiowanie tabeli

    CREATE TABLE Narty ( model VARCHAR(20) PRIMARY KEY, producent VARCHAR(20) );
  • Usuwanie definicji tabeli

    DROP TABLE Narty;

1.8. System zarządzania bazami danych

Realizacja wydajnych baz danych nie jest prosta. Dlatego potrzebujemy wyspecjalizowanego narzędzia: systemu zarządzania bazami danych (DBMS, od Data Base Management System).

W takim systemie baza danych zorganizowana jest tak, aby ułatwić modyfikacje i współbieżną pracę.

  • Do przyśpieszenia wyszukiwania można tworzyć indeksy.

  • Do synchronizacji zadań wielu użytkowników używa się mechanizmu transakcji.

Dodatkowe korzyści z używania DBMS to:

  • Kontrola nadmiarowości (,,redundancji”)

  • Poufność, ograniczanie niepowołanego dostępu

  • Trwała pamięć dla obiektów i struktur danych programów

  • Wdrażanie więzów integralności

  • Archiwizacja i odtwarzanie

  • Automatyczne uruchamianie akcji wywoływane zmianą zawartości bazy

1.9. Transakcje

Transakcje to proste lub złożone operacje na bazie danych, charakteryzowane często skrót ACID od angielskich nazw wymaganych cech:

  • Atomicity czyli niepodzielność: transakcja ma być wykonana w całości albo wcale.

  • Consistency czyli spójność: transakcja przeprowadza bazę danych z legalnego stanu w (być może inny) legalny stan.

  • Isolation czyli izolacja: gdy dwie transakcje są przeprowadzane jednocześnie, ich działania nie mogą na siebie wpływać.

  • Durability czyli trwałość: jeśli transakcja zakończy się pomyślnie, to jej wyniki nie mogą zostać utracone z powodu awarii systemu.

1.9.1. Role

Typowe role związane z bazami danych to:

  • Administratorzy baz danych (DataBase Administrators — DBA)

  • Projektanci baz danych

  • Użytkownicy

    • doraźni

    • zaawansowani

  • Programiści

  • Analitycy systemów (często nazywani administratorami danych).

1.10. Laboratorium

W czasie zajęć w laboratorium będziemy używać publicznie dostępnego DBMS Postgres.

1.10.1. Logowanie do Postgresa

Należy zalogować się do Linuxa na jakąś maszynę w laboratorium.

Chcąc pracować interakcyjnie logujemy się do Postgresa pisząc: psql -h labdb bd nasz-login psql to program do doraźnego dostępu i administrowania bazami danych w Postgresie używający SQL. nasz-login oznacza login w systemie Linux.

Zostaniemy poproszeni o hasło. Początkowe hasło jest proste i musi być zmienione jak najszybciej. Proszę nie używać swoich haseł z Linuxa, ponieważ w pewnych okolicznościach mogą być one widoczne (wprawdzie tylko dla administratorów, ale zawsze to już coś). Po wprowadzeniu poprawnego hasła powinniśmy zobaczyć prompt bd=>

1.10.2. Zmienianie hasła

W odpowiedzi na prompt wpisujemy ALTER USER nasz-login WITH PASSWORD 'nowe-hasło'; Każde polecenie SQL należy kończyć średnikiem.

Przypominam, że SQL nie rozróżnia (poza napisami) dużych i małych liter. Konwencjonalnie będę używał dużych liter do wyróżniania słów kluczowych SQL.

1.10.3. Polecenia psql

Oprócz instrukcji SQL możemy wpisywać polecenia psql. Polecenia psql rozpoczynają się lewym ukośnikiem (backslashem). Polecenie \q służy do kończenia pracy.

Inne przydatne polecenia dają dostęp do interakcyjnej pomocy. \h z nazwą instrukcji SQL (np. \h select lub \h create table) podaje krótki opis składni. Aby dostać listę poleceń psql, należy napisać \?.

Podczas pracy działa ,,historia” — poprzednie polecenia można przywoływać strzałkami pionowymi i edytować.

1.10.4. Tworzenie tabeli

W psql można wykonywać dowolne instrukcje SQL. Można założyć tabelę używając instrukcji CREATE TABLE nazwa-tabeli ( lista-atrybutów-i-ich-typów ); Tekst instrukcji można wprowadzać w jednej lub kilku liniach (prompt w kolejnych zmieni się wtedy na bd), dopóki nie wpiszemy średnika kończącego instrukcję.

Przykład tworzenia tabeli: CREATE TABLE Zwierz ( waga int, imie char(10) );

1.10.5. Klucz główny

Każda tabela powinna mieć zadeklarowany klucz główny: CREATE TABLE nazwa-tabeli ( ..., id typ PRIMARY KEY, ... );

Klucz główny może składać się z kilku kolumn: CREATE TABLE nazwa-tabeli ( atrybuty i ich typy, PRIMARY KEY (a,b,c) );

1.10.6. Wstawianie wierszy

Po utworzeniu tabeli można wstawiać do niej wiersze. Najprościej robi się to instrukcją INSERT: INSERT INTO nazwa-tabeli VALUES(wartość, ...); Kolejność wartości powinna odpowiadać kolejności kolumn w deklaracji tabeli, np. aby wstawić wiersz (10, 'Kropka') do tabeli Zwierz piszemy INSERT INTO Zwierz VALUES(10, 'Kropka');

1.10.7. Przeszukiwanie tabeli

Wiersze tabeli można obejrzeć instrukcją: SELECT * FROM nazwa-tabeli; Program psql wyświetla wyszukane wiersze w postaci tabelki: SELECT * FROM test; waga | imie -------+------------ 10 | Kropka (1 row)

1.10.8. Usuwanie tabeli

Tabelę usuwamy instrukcją DROP TABLE nazwa-tabeli; Czasami trzeba użyć modyfikatora CASCADE DROP TABLE test CASCADE;

Jeżeli chcemy zmienić definicję tabeli, przed wczytaniem zmienionej definicji należy usunąć tabelę.

1.10.9. Informacje o tabelach w bazie danych

Informacje o utworzonych tabelach są trzymane w słownikowych tabelach systemowych, przede wszystkim w tabeli pg_tables. Można wyszukać nazwy wszystkich swoich tabel podając zapytanie: SELECT tablename FROM pg_tables WHERE tableowner = nasz-login;

Listę kolumn tabeli można też obejrzeć używając polecenia psql: \backslashd nazwa-tabeli

1.10.10. Wczytywanie instrukcji SQL z pliku

Zamiast wpisywać instrukcje SQL interakcyjnie można umieścić je w pliku i następnie załadować ten plik poleceniem \backslashi nazwa-pliku na przykład bd=> \backslashi foo.sql

1.10.11. Wczytywanie obcych danych

PostgreSQL pozwala wczytywać i wypisywać dane z tabeli używając plików separowanych. Służy do tego instrukcja COPY: COPY tabela TO 'plik'; Domyślnym separatorem jest znak tabulacji, ale można to zmienić: COPY tabela FROM 'plik' USING DELIMITERS '|';

Ponieważ jednak w instrukcji COPY plik musi znajdować się w katalogu dostępnym dla procesów serwera bazy danych, zwykły użytkownik na ogół nie będzie mógł z niego skorzystać. Zamiast nazwy pliku można jednak podać stdin lub stdout, co spowoduje czytanie ze standardowego wejścia i pisanie na standardowe wyjście (w środowisku użytkownika) COPY tabela TO stdout; COPY tabela FROM stdin USING DELIMITERS '|'; Można wtedy przekierować wejście lub wyjście programu takiego jak psql, np. psql -h labdb bd >gatunki.txt bd=> COPY Gatunki TO stdout USING DELIMITERS '|'; bd=> \backslashq

Treść automatycznie generowana z plików źródłowych LaTeXa za pomocą oprogramowania wykorzystującego LaTeXML.

Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego.

Projekt współfinansowany przez Ministerstwo Nauki i Szkolnictwa Wyższego i przez Uniwersytet Warszawski.