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.
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.
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
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.
Przykładowa relacja może mieć postać następującej tabeli
Narty
model | producent |
---|---|
Cool Minx | Atomic |
Jewel Cristal | Salomon |
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.
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.
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.
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.
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.
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
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;
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
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.
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).
W czasie zajęć w laboratorium będziemy używać publicznie dostępnego DBMS Postgres.
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=>
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.
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ć.
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)
);
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)
);
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');
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)
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ę.
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:
Zamiast wpisywać instrukcje SQL interakcyjnie można umieścić je w pliku
i następnie załadować ten plik poleceniem
na przykład
bd=>
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=>
Treść automatycznie generowana z plików źródłowych LaTeXa za pomocą oprogramowania wykorzystującego LaTeXML.
strona główna | webmaster | o portalu | pomoc
© Wydział Matematyki, Informatyki i Mechaniki UW, 2009-2010. Niniejsze materiały są udostępnione bezpłatnie na licencji Creative Commons Uznanie autorstwa-Użycie niekomercyjne-Bez utworów zależnych 3.0 Polska.
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.