Download as pdf or txt
Download as pdf or txt
You are on page 1of 21

Bazy danych, przestrzenie tabel, pliki danych

1 serwera PostgreSQL

1. Zaloguj się do systemu operacyjnego jako użytkownik postgres. Uruchom serwer PostgreSQL.

/usr/pgsql-13/bin/pg_ctl start

2. Połącz się z serwerem bazy danych za pomocą programu psql. Utwórz tabelę pracownicy(id
serial, nazwisko varchar(20)) i wstaw do niej jeden rekord. Na zakończenie wyświetl
strukturę utworzonej tabeli oraz wykaz wszystkich tabel w bieżącej bazie danych.

psql

create table pracownicy(id serial, nazwisko varchar(20));

insert into pracownicy(nazwisko) values ('Kowalski');

\d pracownicy
\dt
\dt+

select tablename, schemaname from pg_tables;

3. Korzystając nadal z programu psql znajdź nazwę i lokalizację pliku danych, w którym
zapisana jest tabela pracownicy.

select pg_relation_filepath('pracownicy');

4. Korzystając nadal z programu psql wyświetl nazwy dostępnych baz danych, nazwy wszystkich
przestrzeni tabel oraz nazwy wszystkich tabel w bieżącej bazie danych. Opuść program psql.

\l

select datname from pg_database;

\db

select spcname from pg_tablespace;

\q

© 2021 Maciej Zakrzewicz 1


5. Utwórz nową przestrzeń tabel o nazwie mojatbs01 skojarzoną z katalogiem dyskowym
/var/lib/pgsql/13/mojatbs01. Utwórz nową bazę danych o nazwie baza01, wskazując dla
niej domyślną przestrzeń tabel mojatbs01.

mkdir /var/lib/pgsql/13/mojatbs01

psql

create tablespace mojatbs01 location '/var/lib/pgsql/13/mojatbs01';

\db

create database baza01 tablespace mojatbs01;

\l+

6. Podłącz się programem psql do bazy danych baza01. Wyświetl nazwę bieżącej bazy danych.

\c baza01

select current_database();

7. Korzystając nadal z programu psql utwórz w bieżącej bazie danych tabelę faktury(numer
char(6), data date, kwota float). Następnie znajdź nazwę i lokalizację jej pliku
danych. Zwróć uwagę na zapis ścieżki dostępu do pliku danych – zawiera ona odniesienie do
linku symbolicznego, który powstał w katalogu pg_tblspc wewnątrz katalogu Data Directory.

create table faktury(numer char(6), data date, kwota float);

select pg_relation_filepath('faktury');

8. Usuń bazę danych baza01 oraz przestrzeń tabel mojatbs01.

\c postgres
drop database baza01;
drop tablespace mojatbs01;

© 2021 Maciej Zakrzewicz 2


Użytkownicy i uprawnienia

2
serwera bazy danych PostgreSQL

1. Korzystając z psql zmień hasło użytkownika postgres serwera bazy danych PostgreSQL.
Opuść program psql.

alter role postgres password 'postgres';


\q

2. Aby umożliwić uwierzytelnianie użytkowników poprzez podanie hasła, dokonaj modyfikacji


pliku pg_hba.conf:

vi /var/lib/pgsql/13/data/pg_hba.conf

zakomentuj istniejący wiersz konfiguracji dostępu local i host:

# local all all peer

i w jego miejsce dodaj nowy wiersz:

local all all scram-sha-256

3. Zrestartuj serwer PostgreSQL

/usr/pgsql-13/bin/pg_ctl restart

4. Korzystając z programu psql zaloguj się jako użytkownik postgres i utwórz schemat o
nazwie APLIKACJA1.

psql --username=postgres
create schema aplikacja1;

5. W schemacie APLIKACJA1 utwórz dwie tabele - PRODUKTY i MAGAZYNY. Do każdej wstaw po


jednym przykładowym rekordzie.

© 2021 Maciej Zakrzewicz 3


create table aplikacja1.produkty(id integer, nazwa varchar(50));
insert into aplikacja1.produkty values (1, 'iPhone 4');

create table aplikacja1.magazyny(id integer, nazwa varchar(50));


insert into aplikacja1.magazyny values (1, 'Magazyn1');

6. Utwórz nowe konto użytkownika o nazwie PRACOWNIK z hasłem PRACOWNIK.

create role pracownik password 'pracownik' login;

7. Utwórz grupę ODCZYT_TABEL i przydziel do niej uprawnienia SELECT na tabelach PRODUKTY i


MAGAZYNY ze schematu APLIKACJA1. Dodatkowo, przydziel tej grupie prawo do korzystania ze
schematu APLIKACJA1.

create role odczyt_tabel;

grant select on aplikacja1.produkty to odczyt_tabel;


grant select on aplikacja1.magazyny to odczyt_tabel;
grant usage on schema aplikacja1 to odczyt_tabel;

8. Przydziel grupę ODCZYT_TABEL użytkownikowi PRACOWNIK.

grant odczyt_tabel to pracownik;


\q

9. Korzystając z programu psql zaloguj się do bazy danych POSTGRES jako PRACOWNIK z hasłem
PRACOWNIK i spróbuj wykonać zapytanie do tabel PRODUKTY i MAGAZYNY ze schematu
APLIKACJA1. Dla wygody ustaw schemat APLIKACJA1 jako domyślną ścieżkę przeszukiwania.

psql --username=pracownik postgres

select * from aplikacja1.produkty;


set search_path to aplikacja1;
select * from produkty;
select * from magazyny;

10. Spróbuj usunąć rekordy z tabeli PRODUKTY. Co się stało i dlaczego?

delete from produkty;

11. Wyloguj użytkownika PRACOWNIK. Zaloguj się ponownie jako użytkownik postgres. Wyświetl
listę wszystkich ról.

\q

psql --username=postgres

select rolname, rolcanlogin, rolsuper from pg_roles;

© 2021 Maciej Zakrzewicz 4


\du

\duS

12. Wyświetl wszystkie uprawnienia przydzielone do tabeli APLIKACJA1.PRODUKTY.

\dp aplikacja1.produkty

13. Korzystając z widoków systemowych, odczytaj informacje o wszystkich uprawnieniach do


tabel, widoków, funkcji, procedur, schematów i baz danych, dostępnych dla użytkownika
pracownik. Rozważ zarówno uprawnienia przydzielone użytkownikowi pracownik
bezpośrednio, jak i poprzez zawierające go grupy i pseudorolę PUBLIC.

a. nazwy grup, do których należy użytkownik pracownik:

select role_name
from information_schema.applicable_roles
where grantee='pracownik';

b. uprawnienia do tabel i widoków przydzielone bezpośrednio użytkownikowi pracownik,


grupie odczyt_tabel lub wszystkim użytkownikom (PUBLIC):

select table_schema, table_name, privilege_type, grantee


from information_schema.table_privileges
where grantee in ('pracownik','odczyt_tabel', 'PUBLIC');

c. uprawnienia do funkcji i procedur przydzielone bezpośrednio użytkownikowi


pracownik, grupie odczyt_tabel lub wszystkim użytkownikom (PUBLIC):

select routine_schema, routine_name, privilege_type, grantee


from information_schema.routine_privileges
where grantee in ('pracownik','odczyt_tabel', 'PUBLIC');

d. wszystkie uprawnienia do schematów:

select nspname, nspacl from pg_namespace;

e. wszystkie uprawnienia do baz danych (uwaga: uprawnienia predefiniowane nie


pokazują się, jeżeli jawnie nie nadano żadnych innych):

select datname, datacl from pg_database;

(trick, aby zobaczyć uprawnienia predefiniowane do bazy danych postgres)

grant connect on database postgres to postgres;


revoke connect on database postgres from postgres;

select datname, datacl from pg_database;

© 2021 Maciej Zakrzewicz 5


14. Usuń schemat APLIKACJA1 wraz z zawartością.

drop schema aplikacja1 cascade;

15. Usuń konto użytkownika PRACOWNIK oraz rolę ODCZYT_TABEL.

drop role pracownik;


drop role odczyt_tabel;

© 2021 Maciej Zakrzewicz 6


Monitorowanie obciążenia

3 serwera PostgreSQL

Konfiguracja pliku logu

1. Skonfiguruj serwer PostgreSQL tak, aby w pliku logu rejestrował czasochłonne polecenia SQL (np.
trwające dłużej niż 50 ms). W tym celu wyedytuj poniższy parametr w pliku postgresql.conf:

vi /var/lib/pgsql/13/data/postgresql.conf

log_min_duration_statement=50

2. Zrestartuj serwer PostgreSQL.

/usr/pgsql-13/bin/pg_ctl restart

3. Wykonaj poniższe przykładowe polecenia SQL. Niektóre wykonają się szybko, niektóre powoli.
Następnie sprawdź nowe zapisy w pliku logu serwera (/var/lib/pgsql/13/data/log):

select count(*) from generate_series(1,10);


select count(*) from generate_series(1,1000);
select count(*) from generate_series(1,1000000);
select count(*) from generate_series(1,10000000);
select pg_sleep(5);

4. Skonfiguruj serwer PostgreSQL tak, aby moduł AUTO_EXPLAIN automatycznie rejestrował w pliku
logu plany wykonania czasochłonnych zapytań SQL (np. trwających ponad 50 ms). W tym celu
dokonaj poniższych modyfikacji w pliku postgresql.conf.

vi /var/lib/pgsql/13/data/postgresql.conf

log_min_duration_statement=-1
session_preload_libraries='auto_explain'
auto_explain.log_analyze=on
auto_explain.log_min_duration=50

5. Zrestartuj serwer PostgreSQL.

© 2021 Maciej Zakrzewicz 7


/usr/pgsql-13/bin/pg_ctl restart

6. Ponownie wykonaj zapytania z kroku (3). Następnie sprawdź nowe zapisy w pliku logu serwera
(/var/lib/pgsql/13/data/log):

select count(*) from generate_series(1,10);


select count(*) from generate_series(1,1000);
select count(*) from generate_series(1,1000000);
select count(*) from generate_series(1,10000000);
select pg_sleep(5);

Plik logu w formacie CSV

7. Skonfiguruj plik logu w formacie CSV, który będzie rejestrować operacje logowania użytkowników
oraz wykonywane polecenia SQL. W tym celu umieść w pliku postgresql.conf parametry
log_destination (zmodyfikuj istniejący!), log_connections, log_statement:

vi /var/lib/pgsql/13/data/postgresql.conf

log_destination = 'stderr,csvlog'
log_connections = on
log_statement = all

Zrestartuj serwer bazy danych:

/usr/pgsql-13/bin/pg_ctl restart

Sprawdź i zanotuj aktualne nazwy i lokalizacje plików logu:

cat /var/lib/pgsql/13/data/current_logfiles

8. Korzystając z narzędzia psql zaloguj się do serwera oraz wykonaj kilka przykładowych operacji
SQL.

psql
create table pracownicy(id serial, nazwisko varchar(20));
insert into pracownicy(nazwisko) values ('Nowak');
\q

9. Obejrzyj zawartość pliku logu CSV zanotowanego w punkcie 1. Znajdź ślady wykonywanych przez
siebie operacji.

cat /var/lib/pgsql/13/data/log/postgresql-*.csv

10. W celu łatwiejszej analizy załaduj plik logu do tabeli w bazie danych:

psql

© 2021 Maciej Zakrzewicz 8


CREATE TABLE postgres_log
(
log_time timestamp(3) with time zone,
user_name text,
database_name text,
process_id integer,
connection_from text,
session_id text,
session_line_num bigint,
command_tag text,
session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_pos integer,
context text,
query text,
query_pos integer,
location text,
application_name text,
backend_type text,
PRIMARY KEY (session_id, session_line_num)
);
COPY postgres_log FROM '/var/lib/pgsql/13/data/log/nazwa.pliku.csv' WITH csv;

11. Zweryfikuj zawartość pliku logu załadowanego do tabeli postgres_log - odszukaj ślady
wykonywanych przez siebie operacji SQL.

select user_name, log_time, message


from postgres_log where message is not null;

W celu oczyszczenia środowiska, usuń tabelę POSTGRES_LOG (drop table postgres_log), usuń
wszystkie dodane oraz przywróć zmodyfikowane parametry w pliku postgresql.conf i zrestartuj
serwer.

© 2021 Maciej Zakrzewicz 9


Korzystanie ze Statistics Collectora

12. W celu aktywowania pełnej funkcjonalności Statistics Collectora wykonaj poniższe polecenia:

set track_activities=on;
set track_counts=on;
set track_functions='all';
set track_io_timing=on;

13. Pozostań połączony z serwerem bazy danych, a dodatkowo, w oddzielnym oknie uruchom drugi
proces PSQL i nawiąż kolejną sesję z serwerem. Posługując się tą nową sesją, wykonaj zapytanie
do pg_stat_activity w celu wyświetlenia statusu i tekstu ostatniego polecenia wykonywanego
przez sesję/połączenie wykorzystywane w kroku (9):

select pid, datname, usename, state, query, query_start


from pg_stat_activity where datname is not null;

14. Korzystając z pg_stat_all_tables wyświetl nazwy:


a. 5 tabel najczęściej odczytywanych sekwencyjnie (seq scan)
b. 5 tabel najczęściej odczytywanych za pomocą indeksów

select relname, seq_scan from pg_stat_all_tables order by seq_scan desc limit 5;


select relname, idx_scan from pg_stat_all_tables order by idx_scan desc nulls
last limit 5;

© 2021 Maciej Zakrzewicz 10


Logiczne kopie bezpieczeństwa i odtwarzanie

4 bazy danych PostgreSQL

Logiczna kopia bezpieczeństwa i odtwarzanie po awarii

1. Korzystając z narzędzia pg_dump wykonaj logiczną kopię bezpieczeństwa bazy danych o


nazwie postgres.

pg_dump --username=postgres postgres > kopia_logiczna1.sql

2. Obejrzyj zawartość wygenerowanego pliku.

3. "Omyłkowo" usuń tabelę PRACOWNICY z bazy danych POSTGRES.

psql --username=postgres postgres

drop table pracownicy;

\q

4. Korzystając z wykonanej wcześniej logicznej kopii bezpieczeństwa odzyskaj omyłkowo


usuniętą tabelę.

psql --username=postgres postgres < kopia_logiczna1.sql

5. Sprawdź, czy tabela PRACOWNICY została poprawnie odzyskana.

psql --username=postgres postgres

select * from pracownicy;

\q

6. Korzystając z narzędzia pg_dump wykonaj kolejną logiczną kopię bezpieczeństwa bazy danych
o nazwie postgres. Tym razem kopia powinna być skompresowana.

pg_dump --username=postgres --compress=9 -f kopia_logiczna2.sql.gz postgres

7. Korzystając z narzędzia pg_dump wykonaj logiczną kopię bezpieczeństwa struktury bazy


danych o nazwie postgres, zawierającą wyłącznie polecenia SQL, które można wykorzystać
do zbudowania identycznej bazy danych, lecz bez danych. Obejrzyj wygenerowany plik.

pg_dump --username=postgres --schema-only --create -f kopia_logiczna3.sql


postgres

© 2021 Maciej Zakrzewicz 11


Fizyczne kopie bezpieczeństwa i odtwarzanie

5
bazy danych PostgreSQL

Fizyczna kopia bezpieczeństwa i odtwarzanie po awarii

1. Zaloguj się do systemu operacyjnego jako postgres. Na potrzeby gromadzenia archiwalnych


plików WAL utwórz na dysku katalog /var/lib/pgsql/13/arch.

mkdir /var/lib/pgsql/13/arch

2. W pliku konfiguracyjnym postgresql.conf dodaj/wyedytuj parametry aktywujące


archiwizację plików WAL:

vi /var/lib/pgsql/13/data/postgresql.conf

archive_mode=on
archive_command = 'cp %p /var/lib/pgsql/13/arch/%f'

3. Zrestartuj serwer PostgreSQL.

/usr/pgsql-13/bin/pg_ctl restart

4. Aby zasymulować aktywność użytkowników, za pomocą psql 19-krotnie wykonaj polecenie


powielające zawartość tabeli PRACOWNICY. Sprawdź, czy w katalogu
/var/lib/pgsql/13/arch pojawiają się archiwalne pliki WAL.

insert into pracownicy(nazwisko) select nazwisko from pracownicy;


insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;

© 2021 Maciej Zakrzewicz 12


insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
insert into pracownicy(nazwisko) select nazwisko from pracownicy;
\q

ls -l /var/lib/pgsql/13/arch

5. Korzystając z narzędzia pg_basebackup wykonaj fizyczną kopię katalogu Data Directory do


/var/lib/pgsql/13/backups/backup01. Obejrzyj zawartość katalogu, w którym
umieszczona została fizyczna kopia bezpieczeństwa.

pg_basebackup --username=postgres -D /var/lib/pgsql/13/backups/backup01

ls -l /var/lib/pgsql/13/backups/backup01

6. Za pomocą psql zasymuluj aktywność użytkowników "po" wykonaniu kopii bezpieczeństwa.


Policz rekordy w tabeli PRACOWNICY - zanotuj wynik, aby później ocenić powodzenie
odtworzenia bazy danych po awarii.

insert into pracownicy(nazwisko) select nazwisko from pracownicy;


select count(*) from pracownicy;
\q

7. Zatrzymaj serwer PostgreSQL i "omyłkowo" zniszcz jego katalog Data Directory oraz katalog
przestrzeni tabel mojatbs01.

/usr/pgsql-13/bin/pg_ctl stop

rm -r /var/lib/pgsql/13/data

8. Spróbuj uruchomić serwer PostgreSQL z uszkodzoną bazą danych.

/usr/pgsql-13/bin/pg_ctl start

9. W celu odzyskania bazy danych skopiuj wszystkie pliki kopii bezpieczeństwa w oryginalne
lokalizacje.

cp -r /var/lib/pgsql/13/backups/backup01 /var/lib/pgsql/13/data

10. W pliku konfiguracyjnym postgresql.conf ustaw parametr restore_command, opisujący


sposób przywracania archiwalnych plików WAL.

vi /var/lib/pgsql/13/data/postgresql.conf

restore_command = 'cp /var/lib/pgsql/13/arch/%f %p'

11. W katalogu Data Directory utwórz pusty plik recovery.signal, aby zasygnalizować potrzebę
odtworzenia bazy danych za pomocą archiwalnych plików WAL.

© 2021 Maciej Zakrzewicz 13


touch /var/lib/pgsql/13/data/recovery.signal

12. Uruchom serwer PostgreSQL - odtwarzanie stanu bazy danych powinno nastąpić
automatycznie. Ślady odtwarzania możesz odnaleźć w pliku logu w podkatalogu log w Data
Directory. Zauważ też, że zniknął plik recovery.signal.

/usr/pgsql-13/bin/pg_ctl start

tail /var/lib/pgsql/13/data/log/*

13. Za pomocą psql sprawdź liczbę rekordów w tabeli PRACOWNICY. Czy udało się odzyskać
kompletną zawartość bazy danych?

select count(*) from pracownicy;

Notka: pomimo utraty zawartości całego Data Directory, a w tym bieżących plików WAL, nie
doszło do utraty danych, ponieważ serwer przed awarią zatrzymany został ręcznie i zdążył
zarchiwizować dotychczasowe pliki WAL. W sytuacji typowej awarii zaobserwowalibyśmy
jednak częściową utratę danych w związku z utratą ostatniego (ostatnich) pliku WAL.

14. Usuń tabelę PRACOWNICY.

drop table pracownicy;

© 2021 Maciej Zakrzewicz 14


Konfiguracja serwera

6
zapasowego PostgreSQL

1. Metodą klonowania utwórz nową maszynę wirtualną, zawierającą instalację oprogramowania


serwera bazy danych PostgreSQL. Ustaw różne adresy MAC dla kart sieciowych obu maszyn
oraz wybierz tryb komunikacji sieciowej "Bridged". Zanotuj sieciowe adresy IP maszyn
wirtualnych (polecenie ifconfig). W dalszym opisie ćwiczenia jedną z maszyn będziemy
nazywali MASTER, a drugą STANDBY.

a. zatrzymaj maszynę wirtualną

b. sklonuj maszynę wirtualną, wybierając opcję "Generate new MAC addresses"

c. uruchom obie maszyny wirtualne

d. ustaw tryb komunikacji sieciowej jako "Mostkowana karta sieciowa (bridget)" (menu
Urządzenia->Sieć->Ustawienia sieciowe...)

© 2021 Maciej Zakrzewicz 15


e. przyłącz obie maszyny wirtualne do sieci lokalnej (Connect)

f. na każdej z maszyn otwórz okno terminala i odczytaj nadany adres IP (ifconfig)

g. za pomocą komendy ping sprawdź łączność pomiędzy maszynami wirtualnymi

2. (MASTER) Zaloguj się do systemu operacyjnego jako postgres. Korzystając z programu psql
utwórz nowe konto użytkownika, które będzie wykorzystywane do replikacji.

/usr/pgsql-13/bin/pg_ctl start

psql

create role replication password 'replication' replication login;


\q

3. (MASTER) We wcześniejszych ćwiczeniach włączyłeś już archiwizację plików WAL - teraz


upewnij się tylko, że niezbędne parametry nadal znajdują się w pliku postgresql.conf i że
istnieje katalog dyskowy do przechowywania archiwalnych plików WAL.

ls /var/lib/pgsql/13/arch

cat /var/lib/pgsql/13/data/postgresql.conf

archive_mode=on
archive_command = 'cp %p /var/lib/pgsql/13/arch/%f'

4. (MASTER) W pliku konfiguracyjnym postgresql.conf dodaj parametr listen_addresses,


który umożliwi zdalne przyłączanie się serwera STANDBY:

vi /var/lib/pgsql/13/data/postgresql.conf

listen_addresses = '*'

© 2021 Maciej Zakrzewicz 16


5. (MASTER) W pliku konfiguracyjnym pg_hba.conf zezwól serwerowi STANDBY na podłączanie
się do MASTERa, dodając poniższy wiersz (przyłączanie się w trybie Replication z dowolnego
adresu IP).

vi /var/lib/pgsql/13/data/pg_hba.conf

host replication replication 0.0.0.0/0 scram-sha-256

6. (MASTER) Zrestartuj serwer PostgreSQL.

/usr/pgsql-13/bin/pg_ctl restart

7. (MASTER) Korzystając z psql utwórz nową tabelę MIASTA i wstaw do niej jeden rekord.

psql

create table miasta(id serial, nazwa varchar(20));

insert into miasta(nazwa) values ('Warszawa');

8. (STANDBY) Zaloguj się do systemu operacyjnego jako postgres. Wyczyść zawartość katalogu
Data Directory, uprzednio zabezpieczając pliki postgresql.conf i pg_hba.conf. Następnie
wykonaj na maszynie STANDBY kopię bezpieczeństwa bazy danych MASTER (hasło użytkownika
replication: 'replication').

mv /var/lib/pgsql/13/data/*.conf /var/lib/pgsql/13/backups
rm -rf /var/lib/pgsql/13/data/

pg_basebackup -h adres.ip.master -D /var/lib/pgsql/13/data/ -P -U replication


--wal-method=stream

9. (STANDBY) Przywróć oryginalne pliki postgresql.conf i pg_hba.conf. Następnie, edytując


plik postgresql.conf skonfiguruj serwer STANDBY jako hot_standby.

mv /var/lib/pgsql/13/backups/*.conf /var/lib/pgsql/13/data
vi /var/lib/pgsql/13/data/postgresql.conf

hot_standby=on
primary_conninfo='host=adres.ip.master port=5432 user=replication
password=replication'

10. (STANDBY) W katalogu Data Directory utwórz pusty plik standby.signal.

touch /var/lib/pgsql/13/data/standby.signal

11. (STANDBY) Uruchom serwer PostgreSQL - replikacja stanu bazy danych powinna uruchomić się
automatycznie.

© 2021 Maciej Zakrzewicz 17


/usr/pgsql-13/bin/pg_ctl start

12. (STANDBY) Korzystając z programu psql sprawdź zawartość tabeli MIASTA.

psql

select * from miasta;

13. (MASTER) Korzystając z programu psql sprawdź, czy użytkownik REPLICATION podłączył się do
serwera. Następnie dodaj nowy rekord do tabeli MIASTA.

\x
select * from pg_stat_activity where usename = 'replication' ;
\x

insert into miasta(nazwa) values ('Krakow');

14. (STANDBY) Korzystając z programu psql sprawdź czy nowy rekord został zreplikowany do
tabeli MIASTA

select * from miasta;

15. (STANDBY) Korzystając z programu psql przekonaj się, że serwer STANDBY pracuje w trybie
tylko do odczytu

delete from miasta;


\q

16. (STANDBY) Aby zakończyć pracę serwera STANDBY jako zapasowego i aktywować go w trybie
serwera podstawowego, wykonaj polecenie pg_ctl promote.

/usr/pgsql-13/bin/pg_ctl promote

17. (STANDBY) Korzystając z programu psql przekonaj się, że serwer STANDBY pracuje już teraz
w trybie samodzielnym i pozwala na modyfikowanie danych. Zauważ też, że automatycznie
zniknął plik standby.signal.

psql

delete from miasta;


\q

ls /var/lib/pgsql/13/data/standby.signal

© 2021 Maciej Zakrzewicz 18


7 Optymalizator zapytań
serwera PostgreSQL

1. Wykonaj skrypt Performance_DemoBuild.sql. Skrypt tworzy zestaw przykładowych tabel,


zawierających dane losowe: products (5 000 rekordów), cities (6 000 rekordów), salesmen
(1 000 rekordów), sales (1 000 000 rekordów).

2. Za pomocą widoku pg_stats wyświetl statystyki Query Plannera dla utworzonych tabel:

select tablename, attname, null_frac, avg_width, n_distinct from pg_stats


where tablename in ('products', 'cities', 'salesmen', 'sales')
order by 1;

3. W celu uproszczenia dalszych ćwiczeń, tymczasowo wyłącz Parallel Query:

set max_parallel_workers_per_gather=0;

Plany wykonania zapytań

4. Wyświetl wygenerowany plan wykonania dla poniższego zapytania:

select max(amount) from sales


where sale_date between (current_timestamp - interval '1000 day')
and (current_timestamp - interval '100 day');

Czy Query Planner postanowił skorzystać z jakiegoś indeksu?


Wykonaj to zapytanie i zanotuj czas odpowiedzi (skorzystaj z komendy \timing on w psql).

5. Wyświetl wygenerowany plan wykonania dla poniższego zapytania:

select max(amount)
from sales, salesmen, products
where sales.salesman_id = salesmen.salesman_id
and sales.prod_id = products.prod_id
and salesmen.sex='M'
and products.price=400000;

Czy Query Planner postanowił skorzystać z indeksu w celu selekcji według kolumny sex?
Czy Query Planner postanowił skorzystać z indeksu w celu selekcji według kolumny price?
Jaki algorytm łączenia tabel został wybrany?
W jakiej kolejności łączone będą tabele?
Z której tabeli odczytana będzie największa liczba rekordów?

© 2021 Maciej Zakrzewicz 19


6. Utwórz następujące indeksy B-drzewo:
a. na kolumnie PRICE tabeli PRODUCTS (create index i1 on products(price);)
b. na kolumnie NAME tabeli PRODUCTS (create index i2 on products(name);)
c. na kolumnie AMOUNT tabeli SALES (create index i3 on sales(amount);)

Ponownie wyświetl wygenerowany plan wykonania zapytania dla zapytania z kroku (5).
Które z utworzonych indeksów zostały wykorzystane? Dlaczego?

select max(amount)
from sales, salesmen, products
where sales.salesman_id = salesmen.salesman_id
and sales.prod_id = products.prod_id
and salesmen.sex='M'
and products.price=400000;

Indeksy

7. Wyświetl wygenerowany plan wykonania dla poniższego zapytania. Czy Query Planner postanowił
użyć indeksu? Jaki jest szacunkowy koszt planu wykonania zapytania?

select name, imported, price


from products
where prod_id=900;

8. Utwórz indeks B-drzewo na kolumnie PROD_ID tabeli PRODUCTS (create index i4 on


products(prod_id);) i ponownie wyświetl wygenerowany plan wykonania zapytania dla
zapytania z kroku (7). Czy Query Planner postanowił wykorzystać indeks? Jaki jest szacunkowy
koszt planu wykonania zapytania?

select name, imported, price


from products
where prod_id=900;

9. Sprawdź, czy indeksy utworzone w kroku (8) będą wykorzystane przez poniższe zapytania.
Dlaczego?

select name, imported, price


from products
where prod_id between 900 and 1000;

select name, imported, price


from products
where prod_id between 900 and 50000;

select name, imported, price


from products
where name='PRODUCTPRODUCTPRODUCT900';

© 2021 Maciej Zakrzewicz 20


10. W kroku (6) utworzyłeś indeks B-drzewo na kolumnie NAME tabeli PRODUCTS. Sprawdź, czy ten
indeks zostanie użyty przez poniższe zapytania:

select * from products


where name='PRODUCTPRODUCTPRODUCT900';

select * from products


where name like 'PRODUCTPRODUCTPRODUCT9%';

11. W celu wspierania operatorów LIKE/ILIKE, utwórz nowy indeks B-tree n akolumnie NAME tabeli
PRODUCTS, korzystając z opcji text_pattern_ops (create index i2patt on products(name
text_pattern_ops);). Sprawdź, które z poniższych zapytań skorzysta z tego indeksu:

select * from products


where name='PRODUCTPRODUCTPRODUCT900';

select * from products


where name like 'PRODUCTPRODUCTPRODUCT9%';

select * from products


where name like 'PRODUCTPRODUCTPRODUCT%';

select * from products


where name like '%900';

select * from products


where name like 'PRODUCTPRODUCTPRODUCT90%' or
name like 'PRODUCTPRODUCTPRODUCT80%';

12. Wyświetl wygenerowany plan wykonania poniższego zapytania. Czy serwer dokonuje odczytu
tabeli PRODUCTS? Dlaczego?

select count(*)
from products
where price=51000;

13. Wyświetl plany wykonania poniższych zapytań. Czy Query Planner postanowił w obu przypadkach
skorzystać z indeksu? Utwórz nowy indeks na upper(name) i zweryfikuj jego użycie (create
index i5 on products(upper(name));).

select name, imported, price


from products
where name=' PRODUCTPRODUCTPRODUCT23500';

select name, imported, price


from products
where upper(name)=' PRODUCTPRODUCTPRODUCT23500';

© 2021 Maciej Zakrzewicz 21

You might also like