Rozdział 01

Instalacja, architektura i zarządzanie plikami

Instancje, usługi, bazy systemowe, pliki, Filegroups, strony dyskowe i narzędzia administracyjne.

Typy instancji

Domyślna
Zależna od nazwy komputera, jedna na serwer. Łączenie: nazwa_komputera
Nazwana
Niezależne usługi i pliki, wiele na serwer. Łączenie: nazwa_komputera\nazwa_instancji
Uwierzytelnianie Windows
Konta domenowe/lokalne – silnik ufa systemowi, brak hasła
Mixed Mode
Windows + wewnętrzne konta serwera (SQL Server Authentication)
Express (darmowa)
Limit: 4 rdzenie, 1 socket, brak Agent. Do nauki.
Standard (płatna)
Najczęstsza edycja komercyjna
Enterprise
Pełnia możliwości, brak limitów sprzętowych
Developer (darmowa)
= Enterprise, ale zakaz użytku komercyjnego

Kluczowe usługi

MSSQLServer
Główny silnik bazy danych – bez niego nikt się nie połączy
SQLServer Agent
Harmonogramowanie zadań (Joby, Maintenance Plans). Brak w Express!
SSRS
Usługi raportowe
SSAS
Usługi analityczne
DTC
Distributed Transaction Coordinator – transakcje rozproszone

Bazy systemowe

BazaRolaBackup?
MasterMetadane, konta logowania, konfiguracja instancjiTak – po każdej zmianie loginów/konfiguracji
ModelSzablon dla każdej nowo tworzonej bazy (CREATE DATABASE klonuje Model)Opcjonalnie – jeśli personalizujesz
TempdbObiekty tymczasowe, tabele robocze, bufor sortowaniaNigdy! – odtwarza się od zera przy starcie
MsdbJoby, harmonogramy, historia backupów, alertyTak – jeśli masz automatyzację
Sztuczka z Model: Dodanie tabeli do bazy Model spowoduje, że każda nowo tworzona baza (CREATE DATABASE) odziedziczy tę tabelę. Na kolokwium: „każda nowa baza ma mieć tabelę emp" → po prostu utwórz tabelę emp w bazie Model.

Architektura plików

.mdf – plik podstawowy
Główny plik danych (jeden na bazę, obowiązkowy)
.ndf – pliki dodatkowe
Rozszerzenie danych, opcjonalne – przypisywane do Filegroups
.ldf – dziennik transakcji
Log wszystkich modyfikacji (WAL)
Zasada WAL (Write-Ahead Logging): dane najpierw trafiają do dziennika transakcji (.ldf), a dopiero stamtąd zapisywane są w pliku z danymi (.mdf). Gwarantuje spójność po awarii – po restarcie silnik czyta log i odtwarza lub wycofuje niedokończone transakcje.

Strony dyskowe (Pages) i Extenty

Strona (Page)
Jednostka 8 KB – najmniejszy blok I/O
Extent
8 stron = 64 KB – rezerwowany blok dyskowy
Limit rekordu
Jeden wiersz musi zmieścić się na jednej stronie (8 KB)
Ograniczenie 8 KB: Próba wstawienia danych przekraczających ~8060 bajtów w zwykłych typach (np. VARCHAR(10000)) zakończy się błędem. Rozwiązanie: typy LOB – VARCHAR(MAX), NVARCHAR(MAX), VARBINARY(MAX) – przechowują dane na osobnych stronach LOB.

Filegroups – logiczne grupy plików

MS SQL nie pozwala bezpośrednio wskazać ścieżki dyskowej dla tabeli. Zamiast tego stosuje się Filegroups – logiczne kontenery łączące jeden lub więcej plików .ndf na konkretnym dysku.

⬡ SQL (T-SQL)
-- 1. Dodanie Filegroup do bazy ALTER DATABASE [MojaBaza] ADD FILEGROUP [FG_Dane]; -- 2. Dodanie pliku do Filegroup ALTER DATABASE [MojaBaza] ADD FILE ( NAME = 'MojaBaza_Dane1', FILENAME = 'D:\Data\MojaBaza_Dane1.ndf', SIZE = 100MB, FILEGROWTH = 50MB ) TO FILEGROUP [FG_Dane]; -- 3. Tworzenie tabeli w Filegroup CREATE TABLE dbo.Zamowienia ( Id INT PRIMARY KEY, DataZam DATE, Kwota DECIMAL(10,2) ) ON [FG_Dane];
◈ SSMS (interfejs graficzny)
  1. Prawy klik na bazę → Properties
  2. Zakładka Filegroups → Add Filegroup → podaj nazwę (np. FG_Dane)
  3. Zakładka Files → Add → wybierz Filegroup, wskaż ścieżkę dyskową i nazwę pliku .ndf
  4. Przy tworzeniu tabeli (New Table) → w Properties tabeli → ustaw „Filegroup" na FG_Dane
  5. Domyślna grupa: PRIMARY – tam ląduje tabela, jeśli nie podano ON
TEXT/Image Filegroup: Duże obiekty LOB (XML, VARBINARY(MAX)) można wypchnąć na oddzielny, wolniejszy dysk, by nie obciążać głównych plików z danymi.

Shrink – zmniejszanie plików bazy

Po usunięciu milionów rekordów plik bazy nie zmniejsza się automatycznie na dysku. Wolna przestrzeń zostaje „wewnątrz" pliku. Shrink odzyskuje ją dla systemu.

⬡ SQL (T-SQL)
-- Zmniejsz całą bazę DBCC SHRINKDATABASE ('MojaBaza'); -- Zmniejsz konkretny plik DBCC SHRINKFILE ('MojaBaza_Data', 200); -- Sprawdź rozmiar bazy EXEC sp_spaceused; EXEC sp_helpdb 'MojaBaza';
◈ SSMS (interfejs graficzny)
  1. Prawy klik na bazę → Tasks → Shrink → Database / Files
  2. Wybierz typ pliku (Data / Log)
  3. Ustaw docelowy rozmiar
  4. Kliknij OK
Nie nadużywaj Shrink! Częste kurczenie + rozrastanie pliku powoduje zabójczą fragmentację dyskową, rujnując wydajność I/O. Wykonuj tylko w oknach serwisowych i w wyjątkowych sytuacjach.

Narzędzia administracyjne

SSMS
SQL Server Management Studio – główny graficzny interfejs administratora (instalowany osobno)
Configuration Manager
Włączanie usług, konfiguracja protokołów sieciowych (TCP/IP)
Database Engine Tuning Advisor
Automatyczne projektowanie indeksów na podstawie trace'a
SQL Server Profiler
Przechwytywanie i debugowanie zapytań (wykrywa problemy ORM!)
Pułapki SSMS: Otwarte zakładki projektowe (Design) cicho blokują serwer (Locks). Zmiany w jednej zakładce nie pojawią się w innej dopóki nie zapiszesz i nie klikniesz Refresh. Przy DROP DATABASE – włącz „Close Existing Connections" by wyrzucić podpięte sesje.
Rozdział 02

Backup & Restore – kopie zapasowe i odtwarzanie

Strategie backupowe, modele odzyskiwania, typy kopii, mechanika odtwarzania i pułapki SSMS.

Typy kopii zapasowych

MS SQL wspiera Hot Backup – backup wykonuje się w trakcie normalnej pracy użytkowników. Silnik używa logów transakcyjnych do wyrównania stanu, gwarantując spójność. Backup zawiera wszystko: dane, triggery, procedury, uprawnienia i użytkowników.

TypOpisCharakterKiedy stosować
Full (pełna)Kompletna kopia całej bazyPunkt bazowyPodstawa każdej strategii – bez niej nic nie zadziała
Differential (różnicowa)Zmiany od ostatniej kopii pełnej (na poziomie stron 8KB)Różnicowa (nie przyrostowa!)Codziennie; środowa Diff zawiera pon+wt+śr razem
Log (dziennik transakcji)Zapis logiki zmian między kolejnymi backupami loguPrzyrostowa (incremental)Co kilka minut – czyści plik .ldf!
Kopie dziennika transakcji są kluczowe – czyszczą log (zapobiegając niebotycznemu rozrostowi .ldf) i umożliwiają odtworzenie do dowolnego punktu w czasie (STOPAT). Przechowywać na zewnętrznych nośnikach!

Modele odzyskiwania (Recovery Model)

ModelZachowanie loguBackup logu?Point-in-time restore
FullPełne logowanie – log rośnie aż do backupuTak (wymagany!)Tak – do mikrosekundy
Bulk LoggedJak Full, ale nie loguje masowych operacjiTakCzęściowe (nie dla bulk ops)
SimpleAutomatyczne czyszczenie logu po commitNieNie – brak historii modyfikacji
Simple = projekty studenckie/deweloperskie. Full = systemy produkcyjne (obowiązkowy!).

Wykonanie backupu

⬡ SQL (T-SQL)
-- Kopia pełna BACKUP DATABASE [MojaBaza] TO DISK = 'D:\Backup\MojaBaza_Full.bak' WITH COMPRESSION, STATS = 10; -- Kopia różnicowa BACKUP DATABASE [MojaBaza] TO DISK = 'D:\Backup\MojaBaza_Diff.bak' WITH DIFFERENTIAL, COMPRESSION; -- Kopia dziennika transakcji BACKUP LOG [MojaBaza] TO DISK = 'D:\Backup\MojaBaza_Log.trn' WITH COMPRESSION;
◈ SSMS (interfejs graficzny)
  1. Prawy klik na bazę → Tasks → Back Up…
  2. Wybierz typ: Full / Differential / Transaction Log
  3. Destination → Add → wskaż ścieżkę pliku .bak / .trn
  4. UWAGA: Usuń domyślną ścieżkę! Dwa cele = podział backupu na fragmenty!
  5. Options → sprawdź Verify backup / Compression
  6. Kliknij OK

INIT vs NOINIT & przeglądanie pliku

WITH INIT
Nadpisuje plik – kasuje starą zawartość
WITH NOINIT (domyślne)
Dopisuje kolejny backup na koniec pliku – buduje historię
RESTORE HEADERONLY
Wyświetla listę wszystkich kopii w pliku .bak (daty, typy)
⬡ SQL (T-SQL)
-- Podgląd zawartości pliku backupowego RESTORE HEADERONLY FROM DISK = 'D:\Backup\MojaBaza.bak'; -- Podgląd plików logicznych w backupie RESTORE FILELISTONLY FROM DISK = 'D:\Backup\MojaBaza.bak';
◈ SSMS (interfejs graficzny)
  1. Prawy klik na Databases → Restore Database…
  2. Source: Device → „…" → Add → wybierz plik .bak
  3. Kliknij przycisk Contents → widzisz listę kopii w pliku
  4. Wybierz konkretną kopię z listy

Odtwarzanie bazy danych

Prawidłowa kolejność: najnowsza kopia pełna → najnowsza kopia różnicowa (jedna!) → chronologicznie KAŻDY log po różnicowej. Pominięcie jednego logu = przerwanie łańcucha LSN = nieodwracalny błąd!
⬡ SQL (T-SQL)
-- 1. Kopia pełna (nie udostępniaj jeszcze!) RESTORE DATABASE [MojaBaza] FROM DISK = 'D:\Backup\MojaBaza_Full.bak' WITH NORECOVERY, REPLACE; -- 2. Kopia różnicowa RESTORE DATABASE [MojaBaza] FROM DISK = 'D:\Backup\MojaBaza_Diff.bak' WITH NORECOVERY; -- 3. Kolejne logi transakcyjne RESTORE LOG [MojaBaza] FROM DISK = 'D:\Backup\MojaBaza_Log1.trn' WITH NORECOVERY; RESTORE LOG [MojaBaza] FROM DISK = 'D:\Backup\MojaBaza_Log2.trn' WITH NORECOVERY; -- 4. Ostatni krok – udostępnienie bazy RESTORE DATABASE [MojaBaza] WITH RECOVERY; -- Point-in-Time (opcjonalnie) RESTORE LOG [MojaBaza] FROM DISK = 'D:\Backup\MojaBaza_Log3.trn' WITH RECOVERY, STOPAT = '2024-05-01 14:30:00';
◈ SSMS (interfejs graficzny)
  1. Prawy klik na Databases → Restore Database…
  2. Source: Device (nie „Database"!) → dodaj kolejno pliki
  3. SSMS ułoży je automatycznie w kolejności
  4. Options → zaznacz Overwrite existing database (REPLACE)
  5. Dla point-in-time: sekcja Timeline → ustaw konkretny czas
  6. Kliknij OK – SSMS sam ustawi NORECOVERY na pośrednich
NORECOVERY vs RECOVERY: NORECOVERY = baza w stanie „Restoring..." (żółty dopisek) – nie jest dostępna, ale przyjmuje kolejne pliki. RECOVERY = udostępnia bazę, ale zamyka możliwość dogrania kolejnych logów! Użyj RECOVERY TYLKO na ostatnim pliku.
Na kolokwium: zawsze używaj „Device" w GUI – tryb „Database" działa tylko jeśli serwer pamięta historię. W prawdziwej awarii ta historia wyparuje.

WITH MOVE – relokacja plików

Jeśli odtwarzasz bazę na innym serwerze, oryginalne ścieżki (np. D:\Data\) mogą nie istnieć. Użyj WITH MOVE:

⬡ SQL (T-SQL)
-- Relokacja plików przy Restore RESTORE DATABASE [MojaBaza] FROM DISK = 'D:\Backup\MojaBaza.bak' WITH MOVE 'MojaBaza' TO 'C:\Data\MojaBaza.mdf', MOVE 'MojaBaza_Log' TO 'C:\Logs\MojaBaza.ldf', RECOVERY;
◈ SSMS (interfejs graficzny)
  1. Restore Database → zakładka Files
  2. Zaznacz „Relocate all files to folder"
  3. Wskaż nową ścieżkę docelową dla .mdf i .ldf

Backup baz systemowych

BazaKiedy backupowaćSpecjalne wymagania
MasterPo zmianach loginów, konfiguracji serweraRestore wymaga Single User Mode (flaga z wiersza poleceń)
MSDBPo utworzeniu Jobów, alertów, planówStandardowy restore
ModelPo personalizacji szablonuOpcjonalnie
TempDBNIGDYOdtwarza się od zera przy każdym starcie

Awaryjny backup logu (Tail-Log Backup)

Scenariusz: Ktoś zniszczył dane o godz. 12:00. Baza jest uszkodzona, ale plik .ldf wciąż działa.

1
Natychmiast zrób awaryjny backup logu z uszkodzonej bazy (tail-log backup).
2
Odtwórz wczorajszą kopię Full z NORECOVERY.
3
Nałóż awaryjny backup logu z STOPAT = '12:00 minus 1 minuta'.
4
Baza wraca do stanu sprzed katastrofy – cała poranna praca ocalona.
Rozdział 03

Bezpieczeństwo i schematy

Login vs User, hierarchia uprawnień, GRANT/DENY/REVOKE, role, schematy i pułapki SSMS.

Login vs User – dwuetapowy dostęp

1. Login (instancja)
Uwierzytelnienie do serwera. Sam login NIE daje dostępu do baz – dostaniesz „permission denied"
2. User (baza danych)
Mapowanie loginu do bazy. Dopiero User może cokolwiek robić w konkretnej bazie
⬡ SQL (T-SQL)
-- Tworzenie loginu SQL CREATE LOGIN jan_kowalski WITH PASSWORD = 'Haslo!123'; -- Tworzenie loginu Windows CREATE LOGIN [KOMPUTER\jan_kowalski] FROM WINDOWS; -- Tworzenie użytkownika w bazie USE [MojaBaza]; CREATE USER jan_kowalski FOR LOGIN jan_kowalski; -- Nadawanie uprawnień DML GRANT SELECT, INSERT, UPDATE, DELETE ON dbo.Tabela TO jan_kowalski; -- Zakaz (nadrzędny!) DENY DELETE ON dbo.Tabela TO jan_kowalski; -- Dodanie do roli wbudowanej ALTER ROLE db_datareader ADD MEMBER jan_kowalski;
◈ SSMS (interfejs graficzny)
  1. Security → Logins → New Login…
  2. Podaj nazwę, typ: SQL / Windows, hasło
  3. Zakładka User Mapping → zaznacz bazę → przypisz rolę
  4. Kliknij OK
  5. W bazie: Security → Users → Properties
  6. Zakładka Securables → Search → dodaj obiekt (tabelę)
  7. W tabeli zaznacz GRANT lub DENY przy każdym uprawnieniu

Konta specjalne

SA (System Administrator)
Wbudowane konto sysadmin (Mixed Mode). Znane atakującym – używaj z silnym hasłem lub zablokuj!
dbo (database owner)
Właściciel bazy – pełne prawa, ignoruje model bezpieczeństwa. Każdy sysadmin mapowany jako dbo.
guest
Wyjątek: Login BEZ User'a w bazie może wykonywać akcje, jeśli guest ma uprawnienia

Hierarchia uprawnień (3 poziomy)

PoziomPrzykłady uprawnieńPrzypisywane do
SerwerALTER ANY LOGIN, ALTER ANY DATABASE, SHUTDOWNLogin
Baza danychCREATE TABLE, BACKUP DATABASE, SELECT (na wszystkich tabelach)User
ObiektSELECT, INSERT, UPDATE (nawet na kolumnie!), DELETE, EXECUTEUser

GRANT / DENY / REVOKE

GRANT
Nadaje prawo. Wariant WITH GRANT OPTION pozwala oddelegować uprawnienie dalej.
REVOKE
Zdejmuje GRANT – ale user może wciąż mieć dostęp z innej roli!
DENY
Bezwzględny zakaz – nadrzędny wobec GRANT z dowolnego źródła. Specyfika MS SQL!
DENY jest zawsze nadrzędne – unieważnia GRANTy z ról, schematów, wszystkiego. Ale DENY to „środek ratunkowy" – oparcie całej architektury na DENY to porażka administratora.

Role

Serwer
sysadmin diskadmin securityadmin dbcreator
Baza danych
db_owner db_datareader db_datawriter db_ddladmin db_securityadmin
public
Każdy user należy automatycznie – uprawnienie na public = uprawnienie dla WSZYSTKICH
Role aplikacyjne
Zabezpieczone hasłem, aktywowane proceduralnie z poziomu aplikacji – tymczasowe super-uprawnienia

Schematy

Schematy grupują obiekty (tabele, procedury) – jak „foldery" (ale zawsze płaskie, 1-poziomowe). Domyślny schemat to dbo.

⬡ SQL (T-SQL)
-- Tworzenie schematu CREATE SCHEMA logistyka; -- Tworzenie tabeli w schemacie CREATE TABLE logistyka.Wysylki ( Id INT PRIMARY KEY, Data DATE ); -- Uprawnienia na CAŁY schemat GRANT SELECT ON SCHEMA::logistyka TO jan_kowalski; -- Zmiana domyślnego schematu usera ALTER USER jan_kowalski WITH DEFAULT_SCHEMA = logistyka; -- Przeniesienie obiektu między schematami ALTER SCHEMA logistyka TRANSFER dbo.Zamowienia;
◈ SSMS (interfejs graficzny)
  1. Prawy klik na bazę → Security → Schemas → New Schema…
  2. Podaj nazwę (np. logistyka)
  3. W Properties usera → zmień Default Schema
  4. W Securables schematu → nadaj GRANT/DENY
Projektuj uprawnienia na warstwach: schemat → rola → użytkownik. Nigdy nie nadawaj uprawnień „ad hoc" do pojedynczych obiektów.
Przeniesienie obiektu (ALTER SCHEMA TRANSFER) kasuje wszystkie wcześniej nadane uprawnienia obiektowe bez ostrzeżenia!

Pułapki SSMS

  • Search ≠ Grant: Panel Search na górze okna Object Permissions tylko pokazuje listę – uprawnienia nadajesz w dolnej tabeli (Grant/Deny checkboxy).
  • Owner – nie dotykaj! Zmiana Owner/Schemas Owned By This Role rujnuje model zabezpieczeń – Owner ignoruje DENY i cały system uprawnień.
Rozdział 04

Automatyzacja, monitorowanie i integracja

Maintenance Plans, Jobs, monitorowanie, alerty, Full-Text Search, Database Mail, import/eksport danych.

Maintenance Plans – planowane zadania konserwacji

Graficzne narzędzie do „wyklikania" nocnych zadań. Wymaga działającego SQL Server Agent (brak w Express!). Metadane w bazie MSDB.

⬡ SQL (T-SQL)
-- Maintenance Plan generuje pod spodem Joby -- Ale można je programować ręcznie: -- Sprawdzenie integralności DBCC CHECKDB ('MojaBaza') WITH NO_INFOMSGS; -- Aktualizacja statystyk EXEC sp_updatestats; -- Przebudowa indeksów ALTER INDEX ALL ON dbo.Tabela REBUILD; -- Reorganizacja (lżejsza) ALTER INDEX ALL ON dbo.Tabela REORGANIZE;
◈ SSMS (interfejs graficzny)
  1. Management → Maintenance Plans → prawy klik → Maintenance Plan Wizard
  2. Wizard: wybierz zadania (Backup, Rebuild Index, Check Integrity…)
  3. Ustaw harmonogram (Schedule) – np. codziennie o 2:00
  4. Zaawansowany edytor: prawy klik → Modify → edytor wizualny
  5. Łącz zadania strzałkami: zielona (sukces) / czerwona (błąd)
  6. Subplany – oddzielne harmonogramy w jednym planie
  7. „Execute T-SQL Statement" – blok na własny skrypt

Jobs – zadania zaplanowane (niskopoziomowe)

Maintenance Plans tworzą pod spodem Joby. Joby wykraczają poza SQL – krok może być PowerShellem, komendą OS, pakietem SSIS.

⬡ SQL (T-SQL)
-- Tworzenie joba EXEC msdb.dbo.sp_add_job @job_name = 'NocnyBackup'; -- Dodanie kroku EXEC msdb.dbo.sp_add_jobstep @job_name = 'NocnyBackup', @step_name = 'BackupFull', @subsystem = 'TSQL', @command = 'BACKUP DATABASE [MojaBaza] TO DISK = ''D:\Backup\Full.bak'' WITH INIT, COMPRESSION'; -- Dodanie harmonogramu EXEC msdb.dbo.sp_add_schedule @schedule_name = 'Codziennie_2AM', @freq_type = 4, @active_start_time = 020000; EXEC msdb.dbo.sp_attach_schedule @job_name = 'NocnyBackup', @schedule_name = 'Codziennie_2AM'; -- Włączenie joba EXEC msdb.dbo.sp_add_jobserver @job_name = 'NocnyBackup';
◈ SSMS (interfejs graficzny)
  1. SQL Server Agent → Jobs → New Job…
  2. General: nazwa i właściciel
  3. Steps → New: Type = T-SQL / PowerShell / CmdExec / SSIS
  4. Schedules → New: częstotliwość (dziennie / co godzinę)
  5. Notifications: e-mail do Operatora po sukcesie/błędzie
  6. OK – zadanie uruchamia się wg harmonogramu
Złota zasada nauki: Wyklikaj obiekt w SSMS, ale PRZED zapisaniem kliknij prawym → „Script as → to New Query Window". Serwer wygeneruje wzorcowy skrypt – idealny materiał do nauki!

Monitorowanie serwera

Event Viewer (Windows)
Logi aplikacji → filtruj źródło MSSQL. Informacje o Jobach, backupach, błędach krytycznych.
SQL Server Profiler
Przechwytuje KAŻDE zapytanie w czasie rzeczywistym. Trace → zapisz do tabeli → filtruj SQLem.
Performance Monitor
Liczniki MSSQL (prefiksy MSSQL:*) – CPU, I/O, połączenia, blokady. Wykresy wydajnościowe.
Activity Monitor
Prawy klik na serwer → Activity Monitor. Procesy, blokady, oczekiwania.

Alerty i operatorzy

1
Zdefiniuj Operatora (SQL Agent → Operators) – rekord z adresem e-mail osoby z IT.
2
Utwórz Alert reagujący na: SQL Server Event (numer błędu / severity) lub Performance Condition (licznik przekraczający próg).
3
Alert uruchamia ratunkowy Job i/lub wysyła e-mail (Database Mail) do Operatora.
Przykład praktyczny: Alert na zajętość dysku > 90% → automatycznie uruchamia Job który obcina rozpuchnięty log transakcyjny.

Full-Text Search (FTS) – wyszukiwanie pełnotekstowe

Klauzula LIKE jest wolna w ogromnych tekstach. FTS indeksuje każde słowo, rozumie koniugację/deklinację i ignoruje spójniki.

⬡ SQL (T-SQL)
-- 1. Włączenie FTS w bazie EXEC sp_fulltext_database 'enable'; -- 2. Tworzenie katalogu pełnotekstowego CREATE FULLTEXT CATALOG MojKatalog AS DEFAULT; -- 3. Tworzenie indeksu FT (tabela musi mieć PK!) CREATE FULLTEXT INDEX ON dbo.Artykuly ( Tytul, Tresc ) KEY INDEX PK_Artykuly ON MojKatalog WITH CHANGE_TRACKING AUTO; -- Wyszukiwanie słowa SELECT * FROM dbo.Artykuly WHERE CONTAINS(Tresc, 'baza danych'); -- Wyszukiwanie całego zdania (kolejność nieważna) SELECT * FROM dbo.Artykuly WHERE FREETEXT(Tresc, 'optymalizacja zapytań SQL'); -- Ranking trafności SELECT a.*, ft.RANK FROM dbo.Artykuly a INNER JOIN FREETEXTTABLE(dbo.Artykuly, Tresc, 'indeksy wydajność') ft ON a.Id = ft.[KEY] ORDER BY ft.RANK DESC;
◈ SSMS (interfejs graficzny)
  1. Storage → Full Text Catalogs → prawy klik → New Full-Text Catalog
  2. Podaj nazwę katalogu
  3. Prawy klik na tabelę → Full-Text Index → Define Full-Text Index
  4. Wybierz kolumny do indeksowania
  5. Ustaw harmonogram odświeżania katalogu (lub AUTO)
  6. Wymaganie: tabela musi mieć unikalny indeks (PK)
Funkcja FTSOpisZwraca
CONTAINSSzuka dokładnego słowa/frazy w kolumnieTRUE/FALSE (WHERE)
FREETEXTSzuka słów z całego zdania (kolejność nieważna)TRUE/FALSE (WHERE)
CONTAINSTABLEJak CONTAINS, ale z rankingiem trafnościTabela (KEY, RANK)
FREETEXTTABLEJak FREETEXT, ale z rankingiem trafnościTabela (KEY, RANK)

Database Mail

MS SQL nie ma serwera pocztowego. Trzeba skonfigurować profil SMTP (serwer zewnętrzny, port, login).

⬡ SQL (T-SQL)
-- Wysłanie e-maila (po konfiguracji profilu) EXEC msdb.dbo.sp_send_dbmail @profile_name = 'MojProfil', @recipients = 'admin@firma.pl', @subject = 'Alert: Backup FAILED', @body = 'Backup bazy MojaBaza się nie powiódł!';
◈ SSMS (interfejs graficzny)
  1. Management → Database Mail → prawy klik → Configure
  2. Utwórz profil i konto SMTP (serwer, port, login)
  3. Test: prawy klik → Send Test E-Mail
  4. Użyj sp_send_dbmail w Triggerach, Jobach, procedurach
Darmowi dostawcy (Gmail) często odrzucają połączenia od silników bazodanowych jako spam!

Import / Eksport danych

SSIS (Integration Services)
Gigantyczne środowisko ETL – pakiety graficzne i skryptowe do wymiany danych między platformami
GUI Import/Export
SSMS → prawy klik na bazę → Tasks → Import/Export Data. Kreator, mapowanie formatów. Zapisz jako pakiet SSIS.
BCP (Bulk Copy Program)
Najszybsza opcja! Wiersz poleceń: bcp tabela out plik.txt. Bajty wprost do silnika, pomija parsowanie SQL.
BULK INSERT
Komenda T-SQL do masowego ładowania z pliku. Wielokrotnie szybsza niż pętlowy INSERT INTO.
Rozdział 05

Systemy rozproszone i wysoka dostępność

Log Shipping, Mirroring, replikacja, Linked Servers, DTC, Failover Clusters.

Log Shipping

Periodyczne kopiowanie logów transakcyjnych na serwer zapasowy. Model Master-Slave z interwałowym opóźnieniem. 3 automatyczne Joby:

Backup Job
Robi kopię logu na serwerze głównym
Copy Job
Kopiuje plik logu przez udział sieciowy
Restore Job
Odtwarza log na serwerze zapasowym
Tryb serwera zapasowegoZachowanie
StandbyOdczyt możliwy, ale wgranie nowego logu brutalnie odłącza czytających
No RecoveryBaza niedostępna (Restoring) – ciągłe dopisywanie danych

Awaryjne przełączenie: RESTORE DATABASE MojaBaza WITH RECOVERY – budzi zapasową bazę.

Database Mirroring

Przesyłanie transakcji natychmiast po sieci TCP/IP. Szybsze niż Log Shipping, ale wymagające sieciowo.

TrybMechanizmGwarancja
SynchronicznySerwer główny czeka na potwierdzenie z Mirror przed COMMIT100% brak strat, ale większe opóźnienie
AsynchronicznySerwer główny nie czeka – wysyła i commituje natychmiastRyzyko utraty mikrosekund danych „w drodze"
Principal
Serwer główny – obsługuje transakcje
Mirror
Lustrzana kopia – synchronizuje z Principal
Witness (opcjonalny)
Trzecia maszyna-arbiter: nasłuchuje, a gdy Principal padnie – automatyczny Failover → Mirror staje się nowym Principal

Replikacja

Publikator
Udostępnia artykuły (tabele, widoki, procedury)
Dystrybutor
Kolejkuje i rozsyła zmiany (push/pull)
Subskrybent
Odbiera dane

Artykuły mogą być filtrowane: ucinanie kolumn, filtrowanie wierszy (np. pracownicy z Gdańska nie widzą danych z Warszawy).

TypMechanizmZastosowanie
SnapshotPełne zrzuty nadpisujące tabeleMałe bazy, rzadkie zmiany, nocne transfery
TransakcyjnyCiągły ze logu, jednokierunkowyOLTP, real-time (nie edytuj u subskrybenta!)
Peer-to-peerWiele węzłów naraz, niemal real-timeLoad balancing (MS zaleca edycję w jednym węźle)
Scalający (Merge)Obustronny, wielokierunkowy, UID + priorytetyMobilne węzły, offline sync – najkosztowniejszy

Agenci Replikacji

LogReader Agent
Czyta dziennik (model transakcyjny)
Snapshot Agent
Robi zrzuty artykułów
Distribution Agent
Rozpycha/ściąga dane (push/pull)
Merge Agent
Rozwiązuje konflikty (Merge Replication)
Konflikty Merge: Dwa węzły edytują ten sam wiersz. Mechanizm dodaje UUID do rekordów. Domyślnie wygrywa serwer z wyższym priorytetem (Publikator = 100). Istnieją resolwery: średnia arytmetyczna, konkatenacja tekstów, ręczna decyzja administratora.

Linked Servers

Połączenie MS SQL z obcymi bazami (Oracle, DB2, PostgreSQL). Po skonfigurowaniu: poczwórna adresacja w T-SQL.

⬡ SQL (T-SQL)
-- Zapytanie do obcej bazy SELECT * FROM [NazwaLinkedServer].[BazaDanych].[schemat].[tabela]; -- JOIN z lokalną tabelą SELECT l.*, r.Nazwa FROM dbo.Zamowienia l JOIN [ORACLE_SRV].[HR].[dbo].[Employees] r ON l.PracownikId = r.Id; -- Wywołanie zdalnej procedury (RPC) EXEC [ORACLE_SRV].[BazaDanych].dbo.sp_Procedura;
◈ SSMS (interfejs graficzny)
  1. Server Objects → Linked Servers → New Linked Server…
  2. Podaj nazwę, typ dostawcy (SQL Server / Oracle / OLE DB)
  3. Zakładka Security → mapowanie loginów (Remote Login + Password)
  4. Po zapisaniu: rozwijasz Linked Server jak lokalną bazę

Transakcje rozproszone (DTC) – Two-Phase Commit

Gdy skrypt dotyka jednocześnie danych lokalnych i z Linked Server, użyj BEGIN DISTRIBUTED TRANSACTION. Usługa DTC koordynuje protokołem Two-Phase Commit (2PC):

1
Faza Prepare: DTC pyta wszystkie serwery: „Czy jesteście gotowi zacommitować?"
2
Faza Commit: Jeśli WSZYSCY potwierdzili → twardy COMMIT. Jeśli choć JEDEN nie odpowiedział → absolutny ROLLBACK na WSZYSTKICH serwerach, nawet tych które zadziałały prawidłowo. Gwarancja ACID na wielu maszynach.

SQL Server Failover Clusters

Konfiguracja na poziomie Windows Server. Kilka fizycznych serwerów widocznych jako jedna maszyna. Pełna odporność awaryjna + load balancing. MS SQL rezyduje na „farmie serwerowej".

High Availability ≠ Backup! Klastry, mirroring, replikacja nie chronią przed błędem ludzkim – fatalny UPDATE sklonuje się natychmiast na serwer zapasowy. ZAWSZE rób backupy!
Rozdział 06

Metodologia strojenia (Tuning)

Plany wykonania, pomiar IO/czasu, Profiler, Database Engine Tuning Advisor, statystyki kosztowe.

Analiza planu wykonania zapytania

⬡ SQL (T-SQL)
-- Pomiar IO (odczyty logiczne i fizyczne) SET STATISTICS IO ON; GO SELECT * FROM dbo.Tabela WHERE KolumnaId = 100; GO SET STATISTICS IO OFF; -- Pomiar czasu SET STATISTICS TIME ON; GO SELECT * FROM dbo.Tabela WHERE KolumnaId = 100; GO SET STATISTICS TIME OFF; -- Aktualizacja statystyk UPDATE STATISTICS dbo.Tabela; UPDATE STATISTICS dbo.Tabela WITH FULLSCAN;
◈ SSMS (interfejs graficzny)
  1. Wpisz zapytanie w edytorze
  2. Query → Include Actual Execution Plan (Ctrl+M)
  3. Uruchom → zakładka Execution Plan
  4. Grube strzałki = duży transfer danych
  5. Table Scan / Index Scan = brak indeksu
  6. Index Seek = efektywne B+ drzewo
  7. Prawy klik → Properties (koszt, wiersze)
  8. Żółty trójkąt = sugestia brakującego indeksu
Estimated Subtree Cost (lewy górny róg grafu, węzeł SELECT) – jednorodna punktacja niezależna od buforowania. Używaj do porównań „przed" i „po" indeksie.

Kluczowe operacje w planie zapytania

OperacjaZnaczenieOcena
Table ScanPełny odczyt tabeli (heap)Wolno
Index ScanPełny odczyt indeksu (poziome przejście liści)Średnio (ok dla sortowania)
Index SeekNawigacja B+ drzewem od korzeniaSzybko
Key LookupSkok ze strony indeksu do strony danychDo optymalizacji (elimiuj INCLUDEm)
Nested LoopsPętla zagnieżdżona „każdy z każdym"Wolno na dużych zbiorach
Merge JoinŁączenie posortowanych listSzybko
Hash MatchHashowanie do łączeniaŚrednio – zależy od rozmiaru

Statystyki kosztowe i optymalizator

Cost-based optimizer wybiera strategię na podstawie statystyk rozkładu danych. Krytyczne ustawienia serwera:

Auto create statistics
= TRUE (zawsze!)
Auto update statistics
= TRUE (zawsze!)
UPDATE STATISTICS
Ręczna przebudowa – uruchamiaj Jobem w nocy/weekendy
Wyłączenie auto-statystyk = optymalizator podejmuje decyzje „w ciemno" i omija nawet doskonałe indeksy. Nigdy nie wyłączaj!

SQL Server Profiler + Database Engine Tuning Advisor

1
Uruchom Profiler (Tools → Profiler) – rejestruj ruch z reprezentatywnego okresu.
2
Zapisz Trace do pliku .trc lub tabeli.
3
Otwórz Tuning Advisor (Tools → DTA) – załaduj trace + wybierz bazę.
4
Start Analysis – DTA przeanalizuje i wygeneruje skrypty CREATE INDEX z szacunkiem zysku (np. 40% szybciej).
5
Zastosuj skrypty natychmiast lub zaplanuj na okno serwisowe.
Analizuj na bazie testowej (replice), by operacja kosztowa DTA nie obciążała produkcji!
Rozdział 07

Techniki optymalizacji

Dyski, indeksy B+ tree, Fill Factor, defragmentacja, T-SQL, transakcje, izolacja, blokady, MVCC.

Architektura dyskowa

Separacja IO
OS, .mdf i .ldf na osobnych dyskach – eliminuje rywalizację głowic
Tabele i indeksy
Odseparuj indeksy do osobnego pliku/dysku przy ciężkim obciążeniu
RAID 10 (0+1)
Zalecany – min. 4 dyski, wydajność + bezpieczeństwo
RAID 5
Alternatywa, mniej dysków ale wolniejszy zapis
RAID 0
Brak bezpieczeństwa – tylko dla danych tymczasowych!

Indeksy – architektura B+ drzewa

TypCharakterystykaKiedy stosować
ClusteredSortuje fizycznie dane. Jeden na tabelę. Liście = rekordy. Domyślnie na PK.BETWEEN, ORDER BY, GROUP BY (zakresy)
Non-clusteredWskazanie do rekordów. Do 249 na tabelę. Liście = wskaźniki.Równości (=), klucze obce, kolumny WHERE
WielokolumnowyDo 16 kolumn, klucz max 900 bajtów. Kolejność kolumn kluczowa! Musi być użyta 1. kolumna.Filtrowanie po wielu kolumnach

Kiedy indeks NIE pomoże

  • Małe tabele (< 10 000 rekordów) – silnik i tak je szybko skanuje
  • Niska selektywność – milion wpisów, ale 50 unikalnych wartości → indeks bezużyteczny
  • Masowo pisane, rzadko czytane tabele – koszt utrzymania indeksów przy INSERT/UPDATE przewyższa zysk

Tworzenie i zarządzanie indeksami

⬡ SQL (T-SQL)
-- Indeks niepogrupowany z INCLUDE (covering) CREATE NONCLUSTERED INDEX IX_Tabela_Kol ON dbo.Tabela (KolumnaA, KolumnaB) INCLUDE (KolumnaC, KolumnaD) WITH (FILLFACTOR = 80); -- Indeks pogrupowany (NIE na PK!) CREATE CLUSTERED INDEX CX_Tabela ON dbo.Tabela (DataTransakcji); -- Computed column (zamiennik indeksu funkcyjnego) ALTER TABLE dbo.Tabela ADD NazwaLower AS LOWER(Nazwa) PERSISTED; CREATE INDEX IX_NazwaLower ON dbo.Tabela(NazwaLower); -- Reorganizacja / Przebudowa ALTER INDEX IX_Tabela_Kol ON dbo.Tabela REORGANIZE; ALTER INDEX ALL ON dbo.Tabela REBUILD;
◈ SSMS (interfejs graficzny)
  1. Rozwiń tabelę → Indexes
  2. Prawy klik → New Index
  3. Dodaj kolumny klucza + Included Columns
  4. Options: Fill Factor (np. 80)
  5. Przebudowa: prawy klik → Rebuild / Reorganize
  6. Fragmentacja: Properties → Fragmentation
Strategia „tylko indeks" (Covering): Użyj INCLUDE by dodać kolumny SELECTa do liści indeksu. Eliminuje Key Lookup – silnik pobiera wszystko z indeksu, nie dotykając pliku tabeli.
Nigdy nie umieszczaj kolumny w funkcji w WHERE! WHERE YEAR(Data) = 1990 → Table Scan. Przepisz: WHERE Data BETWEEN '1990-01-01' AND '1990-12-31'. Alternatywa MS SQL: kolumna wyliczana (computed column) z indeksem.

Fill Factor i defragmentacja indeksów

Fill Factor
% wypełnienia stron. Domyślnie 0 (=100%). Dla insertowanych tabel: 70-80% → rezerwuje miejsce, eliminuje Page Splits.
Page Split
Przepełniona strona dzieli się na dwie. Kosztowna operacja I/O – spowalnia INSERTy.
Fragmentacja > 20%
Sygnał do przebudowy indeksu
REORGANIZE
Lżejsze – układa liście, online. Dla fragmentacji 10-30%.
REBUILD
Pełna przebudowa B+ drzewa od zera. Blokuje procesy! Tylko w oknach serwisowych.

Optymalizacja T-SQL

  • Unikaj kursorów – operacje set-based (JOIN) wielokrotnie szybsze
  • Problem N+1 (ORM) – Spring/Hibernate generują kaskady zapytań. Wykrywaj Profilerem, przenoś logikę do procedur składowanych.
  • Ograniczaj podzapytania – zastąp JOINem
  • DISTINCT tylko gdy potrzebny – kosztowny na dużych zbiorach
  • Minimalizuj wyzwalacze – niewidzialny narzut przy każdym DML
  • Tabele tymczasowe – opłacalne tylko przy wielokrotnym użyciu ciężkiego wyniku
  • Denormalizacja w raportach – nocne zrzuty do płaskich tabel raportowych

ACID i praktyka transakcji

Atomicity
„Wszystko albo nic" – transakcja wchodzi w całości lub wycofuje się
Consistency
Brak anomalii logicznych po zakończeniu
Isolation
Każdy użytkownik „jak gdyby sam"
Durability
Zacommitowane = zapisane na stałe (WAL)
⬡ SQL – transakcje
-- OBOWIĄZKOWE zabezpieczenie! SET XACT_ABORT ON; BEGIN TRANSACTION; UPDATE dbo.Konta SET Saldo -= 100 WHERE KontoId = 1; UPDATE dbo.Konta SET Saldo += 100 WHERE KontoId = 2; COMMIT TRANSACTION; -- SAVE TRANSACTION – punkt zapisu BEGIN TRANSACTION; INSERT INTO dbo.Log VALUES ('start'); SAVE TRANSACTION SP1; UPDATE dbo.Dane SET X = 5 WHERE Id = 1; -- coś poszło nie tak: ROLLBACK TRANSACTION SP1; -- cofnij tylko do SP1 INSERT INTO dbo.Log VALUES ('rollback częściowy'); COMMIT TRANSACTION; -- Wyłączenie autocommit (eksperymenty) SET IMPLICIT_TRANSACTIONS ON; -- teraz UPDATE nie commituje się automatycznie -- musisz ręcznie: COMMIT lub ROLLBACK
◈ SSMS – zarządzanie transakcjami
  1. Każda operacja DML/DDL jest automatycznie transakcją
  2. Autocommit jest domyślny – każdy UPDATE od razu commituje
  3. SET IMPLICIT_TRANSACTIONS ON → „zwolnione tempo"
  4. Activity Monitor → widok aktywnych transakcji i blokad
  5. ⚠️ Nie zostawiaj otwartej transakcji – blokujesz serwer!
SET XACT_ABORT ON jest OBOWIĄZKOWE w każdym skrypcie z BEGIN TRAN! Bez niego: drobny błąd (naruszenie klucza itp.) jest „przeskakiwany" – transakcja jedzie dalej, łamiąc atomowość. Z XACT_ABORT: dowolny błąd = natychmiastowy ROLLBACK całości.

Anomalie współbieżności

AnomaliaOpisPrzykład
Dirty ReadOdczyt danych z niezacommitowanej transakcjiUser A czyta wynik UPDATE od User B, ale B robi ROLLBACK → dane fałszywe
Non-repeatable ReadDwa odczyty tej samej komórki dają różne wynikiSELECT saldo → 1000. Ktoś robi UPDATE. SELECT saldo → 500.
PhantomPojawiają się nowe rekordy w trakcie transakcjiSELECT COUNT → 10. Ktoś robi INSERT. SELECT COUNT → 11.

Poziomy izolacji

PoziomDirty ReadNon-repeatablePhantomWydajność
READ UNCOMMITTEDTAKTAKTAKNajszybszy
READ COMMITTED (domyślny)NIETAKTAKStandardowy
REPEATABLE READNIENIETAKWolniejszy
SERIALIZABLENIENIENIENajwolniejszy (mrozi tabele!)
SNAPSHOTNIENIENIESzybki (MVCC, bez blokad)
⬡ SQL – poziomy izolacji
-- Ustawianie poziomu (PRZED begin tran!) SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL SNAPSHOT; -- Aktywacja SNAPSHOT w bazie (jednorazowo) ALTER DATABASE [MojaBaza] SET ALLOW_SNAPSHOT_ISOLATION ON; -- Brudny odczyt (hint) – świadomie! SELECT * FROM dbo.Tabela WITH (NOLOCK);
◈ SSMS – izolacja
  1. Baza → Properties → Options → Is Read Committed Snapshot On
  2. Activity Monitor → Resource Waits → LOCK, IO
  3. Deadlock: Trace Flag 1222 lub SQL Server Error Log
SNAPSHOT eliminuje „czytelnik blokuje pisarza" – używa wielowersyjności (MVCC). Idealna dla ciężkich raportów na produkcji. Ale: zużywa pamięć na migawki i przy konflikcie dwóch UPDATEów – wyrzuca błąd.
Złota reguła: Nakładaj NAJNIŻSZY bezpieczny poziom. Domyślny READ COMMITTED wystarcza w 90% przypadków. SERIALIZABLE „na zapas" = lawinowy przyrost blokad.

Blokady (Locks) i Deadlock

Shared Lock (S)
SELECT – tysiące czytających naraz, ale blokuje pisarzy
Exclusive Lock (X)
INSERT/UPDATE/DELETE – nikt inny nie wchodzi
ROW lock
Blokada jednego rekordu
PAGE lock
Blokada strony 8 KB
TABLE lock
Blokada całej tabeli (UPDATE bez WHERE, SERIALIZABLE)
Deadlock
Dwie transakcje czekają nawzajem na swoje zasoby → optymalizator zabija jedną po timeout

Database Snapshots (Enterprise)

Klonowanie bazy do read-only kopii z danego punktu w czasie. Lekkie (copy-on-write). Idealne do raportów: „zamroź stan z godz. 12:00 dla księgowości".

Indeksowane perspektywy (Indexed Views)

MS SQL nie ma MATERIALIZED VIEW. Zamiast tego: fizyczny indeks clustered na widoku. Ograniczenia:

  • Wymaga WITH SCHEMABINDING
  • Brak OUTER JOIN, DISTINCT, MIN/MAX, UNION
  • Użyj COUNT_BIG zamiast COUNT
  • Auto-optymalizacja: tylko Enterprise. Na Standard/Express: wymuś WITH (NOEXPAND)
Indeksy funkcyjne: MS SQL ich nie obsługuje natywnie (PostgreSQL tak). Obejście: computed column (np. AS LOWER(Nazwa) PERSISTED) + indeks na niej.
Rozdział 08

Dobre praktyki i ostrzeżenia

Pułapki indeksów, transakcje, uprawnienia, ORM, porównanie z PostgreSQL, ściągawka diagnostyczna.

Pułapki indeksów i optymalizacji

Funkcja w WHERE = śmierć indeksu. WHERE sal * 12 = 12000 → Table Scan. WHERE sal = 1000 → Index Seek.
Zbyt wiele indeksów na małych tabelach. Koszt utrzymania (IO+CPU przy INSERT/UPDATE/DELETE) może przewyższać zysk SELECTa.
Clustered Index ≠ zawsze PK. Jeśli potrzebujesz zakresu (BETWEEN po dacie), zdejmij Clustered z PK i przenieś na kolumnę z zakresami.

Dobre nawyki – transakcje

  • Krótkie transakcje – dziel na mniejsze bloki, by nie blokować innych
  • SET XACT_ABORT ON – ZAWSZE przed BEGIN TRAN. Bez tego: drobny błąd nie wycofuje transakcji!
  • Nie używaj SERIALIZABLE „na zapas" – mrozi tabele. READ COMMITTED wystarcza w 90% przypadków.
  • WITH (NOLOCK) tylko świadomie – brudne odczyty z niezatwierdzonych/wycofanych transakcji
  • Nie zostawiaj otwartej transakcji (IMPLICIT_TRANSACTIONS ON) – blokujesz serwer

Dobre nawyki – uprawnienia

  • Projektuj: schemat → rola → użytkownik
  • Nigdy nie łącz aplikacji jako sysadmin/SA – zasada minimalnych uprawnień!
  • Role niestandardowe zamiast ról wbudowanych dla granularnej kontroli
  • Role aplikacyjne do dostępu z poziomu aplikacji

Problem N+1 (ORM)

Frameworki ORM (Spring, Hibernate, Entity Framework) generują kaskady zapytań – podręcznikowy „problem N+1": 1 zapytanie po listę + N zapytań po szczegóły każdego elementu. Wykrywaj Profilerem, przenoś logikę do procedur składowanych na serwerze.

MS SQL vs PostgreSQL

FunkcjaPostgreSQLMS SQL Server
Indeksy funkcyjneCREATE INDEX ON t (lower(col)) – natywnieBrak. Computed column + indeks
Zmaterializowane widokiMATERIALIZED VIEW – natywnieIndexed View z SCHEMABINDING (auto-optymalizacja tylko Enterprise)
Hint wymuszający widokNie wymaganyWITH (NOEXPAND) na Standard/Express
Izolacja SNAPSHOTDomyślna (MVCC)Wymaga ALTER DATABASE SET ALLOW_SNAPSHOT_ISOLATION ON
Indeksy haszowaneTak – szybkie na = ale brak sortowaniaBrak
Indeksy bitmapoweBrakBrak (Oracle ma natywnie)

Ściągawka poleceń diagnostycznych

DBCC CHECKDB
Kontrola integralności bazy danych
DBCC SHRINKDATABASE
Zmniejszenie plików (tylko serwisowo!)
SET STATISTICS IO ON
Odczyty logiczne i fizyczne
SET STATISTICS TIME ON
Czas kompilacji i wykonania
UPDATE STATISTICS
Odświeżenie statystyk (WITH FULLSCAN)
sp_helpdb / sp_spaceused
Rozmiar bazy, plików, wolne miejsce
sp_who2
Lista aktywnych połączeń / procesów
RESTORE HEADERONLY
Lista kopii w pliku .bak
Rozdział 09

🎯 Kolokwium – przewodnik i rozwiązania

6 zadań, 10 punktów. Pełne rozwiązania dla każdego typu zadania + przykładowe kolokwium.

Informacje organizacyjne

✅ Dozwolone
Oficjalna dokumentacja Microsoft (learn.microsoft.com), notatki własne, materiały z Edux
❌ Zabronione
AI (ChatGPT), Google, komunikatory (Teams, poczta). Komunikator w tle = przerwanie kolokwium!
📝 Forma
Rozwiązania na kartkach (własny długopis!). Demo na komputerze – wołaj prowadzącego tylko gdy GOTOWE.
⚠️ Pliki backupowe
Każdy zestaw ma DEDYKOWANY plik na FTP. Wzięcie cudzego = złe wyniki = niezaliczenie!
Zadanie 1
Pliki i bazy danych – Filegroups / baza Model
1 punkt

Typowe polecenie: „Umieść tabelę X fizycznie w pliku na dysku D:" lub „Spraw, by każda nowo tworzona baza miała tabelę emp".

Wariant A: Filegroup

⬡ SQL
-- Filegroup + plik + tabela ALTER DATABASE [MojaBaza] ADD FILEGROUP [FG_Zadanie]; ALTER DATABASE [MojaBaza] ADD FILE ( NAME = 'Plik_Zadanie', FILENAME = 'D:\Data\Plik_Zadanie.ndf', SIZE = 10MB ) TO FILEGROUP [FG_Zadanie]; CREATE TABLE dbo.TabelaX ( Id INT PRIMARY KEY, Nazwa VARCHAR(100) ) ON [FG_Zadanie];
◈ SSMS
  1. Baza → Properties → Filegroups → Add → „FG_Zadanie"
  2. Zakładka Files → Add → nazwij plik, ustaw ścieżkę D:\, Filegroup = FG_Zadanie
  3. New Table → w Properties tabeli → Filegroup = FG_Zadanie

Wariant B: Baza Model (każda nowa baza ma tabelę emp)

⬡ SQL
-- Dodaj tabelę do bazy Model USE model; CREATE TABLE dbo.emp ( Id INT PRIMARY KEY IDENTITY, Imie VARCHAR(50), Nazwisko VARCHAR(50), Stanowisko VARCHAR(100), Pensja DECIMAL(10,2) ); -- Teraz każda nowa baza będzie miała emp: CREATE DATABASE TestBaza; USE TestBaza; SELECT * FROM dbo.emp; -- tabela istnieje!
◈ SSMS
  1. Rozwiń bazę „model" → Tables
  2. Prawy klik → New Table… → zdefiniuj kolumny emp
  3. Zapisz (Ctrl+S) → podaj nazwę: emp
  4. Od teraz każda CREATE DATABASE klonuje model z tabelą emp
📖 Docs: Database Files and Filegroups
Zadanie 2
Wydajność i indeksy
2 punkty

Typowe polecenie: „Dostajesz powolne zapytanie z JOINem – zbadaj plan wykonania i zaproponuj indeks" lub „Skonfiguruj Full-Text Search na tabeli X".

Wariant A: Analiza planu i indeks

⬡ SQL
-- 1. Włącz plan i zbadaj zapytanie SET STATISTICS IO ON; -- Ctrl+M w SSMS (Include Actual Execution Plan) -- 2. Zapytanie do optymalizacji SELECT o.OrderId, o.OrderDate, c.Name FROM dbo.Orders o JOIN dbo.Customers c ON o.CustomerId = c.Id WHERE o.OrderDate > '2024-01-01' ORDER BY o.OrderDate; -- 3. Widzisz Table Scan / Index Scan → załóż: -- Clustered na zakres dat CREATE CLUSTERED INDEX CX_Orders_Date ON dbo.Orders (OrderDate); -- Non-clustered na klucz obcy (JOIN) CREATE NONCLUSTERED INDEX IX_Orders_Customer ON dbo.Orders (CustomerId) INCLUDE (OrderDate); -- 4. Uruchom ponownie – powinno być Index Seek
◈ SSMS
  1. Wpisz zapytanie → Ctrl+M → Execute
  2. Zakładka Execution Plan → szukaj Table Scan (czerwone!)
  3. Żółty trójkąt = sugestia „Missing Index"
  4. Prawy klik na sugestię → „Missing Index Details"
  5. Kliknij → otrzymujesz gotowy CREATE INDEX
  6. Uruchom CREATE INDEX → ponownie uruchom zapytanie
  7. Sprawdź: teraz powinno być Index Seek (zielone)

Wariant B: Full-Text Search

Patrz: Rozdział 4 → Full-Text Search

📖 Docs: Indexes 📖 Docs: Full-Text Search
Zadanie 3
Transakcje – scenariusz dwóch sesji
2 punkty – pisemne, bez komputera

Typowe polecenie: „Dwie sesje A i B pracują jednocześnie. Odtwórz kroki i napisz jaki będzie wynik każdego SELECTa."

Jak rozwiązywać:

1
Sprawdź poziom izolacji każdej sesji (domyślny = READ COMMITTED).
2
Sprawdź tryb transakcji: autocommit (domyślny) vs explicit (BEGIN TRAN) vs implicit (SET IMPLICIT_TRANSACTIONS ON).
3
Dla każdego kroku określ: UPDATE/INSERT stawia X lock (wyłączny), SELECT stawia S lock (współdzielony).
4
S lock pozwala innym S lockom ale blokuje X. X lock blokuje wszystko. Blokada trwa do COMMIT/ROLLBACK.
5
Uwzględnij specyfikę poziomu izolacji: READ UNCOMMITTED → czyta nawet niezacommitowane dane. READ COMMITTED → czeka aż X lock się zwolni. SNAPSHOT → czyta migawkę sprzed transakcji.

Przykład rozwiązania scenariusza:

Stan początkowy: tabela Konta: Saldo = 1000 (KontoId=1). Obie sesje: READ COMMITTED, autocommit.

KrokSesja ASesja BWynik
1BEGIN TRANA otwiera transakcję
2UPDATE Konta SET Saldo=500 WHERE KontoId=1A stawia X lock. Saldo=500 (niezacommitowane)
3SELECT Saldo FROM Konta WHERE KontoId=1B CZEKA (blokada!) – READ COMMITTED nie czyta niezacommitowanych
4COMMITA commituje, X lock zwolniony
5(odblokowany)B zwraca: Saldo = 500

Gdyby B miał READ UNCOMMITTED → w kroku 3 zwróciłby 500 (dirty read) bez czekania.

📖 Docs: Transactions 📖 Docs: SET TRANSACTION ISOLATION LEVEL
Zadanie 4
Bezpieczeństwo – login, user, schemat, uprawnienia
2 punkty – demo na komputerze (Access Denied)

Typowe polecenie: „Utwórz login SQL, usera w bazie X, schemat, tabelę w schemacie, nadaj tylko SELECT+INSERT, wykaż brak DELETE."

⬡ SQL – pełne rozwiązanie
-- 1. Login CREATE LOGIN testowy WITH PASSWORD = 'Test!123'; -- 2. User w bazie USE [MojaBaza]; CREATE USER testowy FOR LOGIN testowy; -- 3. Schemat + tabela CREATE SCHEMA zadanie; CREATE TABLE zadanie.Dane ( Id INT PRIMARY KEY IDENTITY, Wartosc VARCHAR(100) ); INSERT INTO zadanie.Dane VALUES ('test'); -- 4. Uprawnienia (tylko DML, BEZ DELETE) GRANT SELECT, INSERT, UPDATE ON SCHEMA::zadanie TO testowy; DENY DELETE ON SCHEMA::zadanie TO testowy; -- 5. Default schema (opcjonalnie) ALTER USER testowy WITH DEFAULT_SCHEMA = zadanie; -- 6. TEST: połącz się jako testowy i sprawdź -- SELECT * FROM zadanie.Dane; → ✅ działa -- INSERT INTO zadanie.Dane VALUES ('nowy'); → ✅ -- DELETE FROM zadanie.Dane WHERE Id=1; → ❌ Access Denied!
◈ SSMS – demo
  1. Security → Logins → New Login… → SQL Auth, hasło
  2. User Mapping → zaznacz bazę
  3. W bazie: New Schema → „zadanie"
  4. New Table w schemacie → dodaj kolumny
  5. User → Properties → Securables → Search → Schema
  6. Zaznacz GRANT na SELECT/INSERT/UPDATE
  7. Zaznacz DENY na DELETE
  8. Demo: Otwórz NOWE połączenie jako testowy (File → Connect Object Explorer → SQL Auth)
  9. Wykonaj DELETE → pokaż prowadzącemu „Access Denied"
Na kolokwium: Przygotuj testowy skrypt DELETE i pokaż prowadzącemu wynik „Access Denied" dopiero gdy WSZYSTKO jest gotowe!
📖 Docs: Getting Started with Database Engine Permissions
Zadanie 5
Backup & Restore – odtworzenie z plików
2 punkty

Typowe polecenie: „Na FTP masz pliki .bak i .trn. Odtwórz bazę do najnowszego stanu (lub do punktu w czasie). Podaj wynik SELECTa."

Procedura krok po kroku:

1
Ściągnij swoje pliki z FTP (pilnuj nazwy zestawu!).
2
RESTORE HEADERONLY FROM DISK = 'ścieżka' – sprawdź co jest w każdym pliku (typ, data).
3
Zidentyfikuj: najnowszy Full → najnowszy Diff PO nim → wszystkie Log PO Diff.
4
Restore Full WITH NORECOVERY, REPLACE → Diff WITH NORECOVERY → Logi WITH NORECOVERY → ostatni WITH RECOVERY (lub STOPAT).
5
Uruchom SELECT i przepisz wynik na kartkę.
⬡ SQL
-- Sprawdź zawartość plików RESTORE HEADERONLY FROM DISK = 'C:\Backup\plik1.bak'; RESTORE HEADERONLY FROM DISK = 'C:\Backup\plik2.bak'; RESTORE HEADERONLY FROM DISK = 'C:\Backup\plik3.trn'; -- Restore (ścieżki przykładowe) RESTORE DATABASE [Zad5] FROM DISK = 'C:\Backup\plik1.bak' WITH NORECOVERY, REPLACE; RESTORE DATABASE [Zad5] FROM DISK = 'C:\Backup\plik2.bak' WITH NORECOVERY; RESTORE LOG [Zad5] FROM DISK = 'C:\Backup\plik3.trn' WITH RECOVERY; -- Opcja: point-in-time -- WITH RECOVERY, STOPAT = '2024-06-15 11:59:00'; -- Wynik USE [Zad5]; SELECT * FROM dbo.Tabela;
◈ SSMS
  1. Databases → prawy klik → Restore Database…
  2. Source: Device → „…" → Add → dodaj WSZYSTKIE pliki
  3. SSMS posortuje je automatycznie (zaznacz „Restore" przy każdym)
  4. Options → Overwrite existing database
  5. Dla point-in-time: Timeline → ustaw czas
  6. Jeśli błąd ścieżek: zakładka Files → „Relocate all files"
  7. OK → uruchom SELECT
📖 Docs: Restore a Database Backup Using SSMS
Zadanie 6
Narzędzia – Maintenance Plan / Job / FTS
1 punkt

Typowe polecenie: „Załóż Maintenance Plan z backupem Full codziennie o 2:00" lub „Utwórz Job z krokiem T-SQL" lub „Włącz Full-Text na tabeli X".

⬡ SQL – Job z backupem
-- Szybki Job: backup co noc EXEC msdb.dbo.sp_add_job @job_name='BackupNocny'; EXEC msdb.dbo.sp_add_jobstep @job_name='BackupNocny', @step_name='FullBackup', @subsystem='TSQL', @command='BACKUP DATABASE [MojaBaza] TO DISK=''D:\Backup\Full.bak'' WITH INIT, COMPRESSION'; EXEC msdb.dbo.sp_add_schedule @schedule_name='Codziennie2AM', @freq_type=4, @active_start_time=020000; EXEC msdb.dbo.sp_attach_schedule @job_name='BackupNocny', @schedule_name='Codziennie2AM'; EXEC msdb.dbo.sp_add_jobserver @job_name='BackupNocny';
◈ SSMS – Maintenance Plan
  1. Management → Maintenance Plans → prawy klik → Maintenance Plan Wizard
  2. Podaj nazwę planu
  3. Zaznacz: „Back Up Database (Full)"
  4. Wybierz bazę (MojaBaza)
  5. Ustaw ścieżkę docelową (D:\Backup\)
  6. Schedule: codziennie, 2:00 AM
  7. Finish – plan utworzony, Agent go uruchomi o 2:00
📖 Docs: Maintenance Plans

📋 Przykładowe kolokwium z rozwiązaniem

Poniższy zestaw symuluje realistyczne kolokwium ABD (6 zadań, 10 pkt). Rozwiązania podano w SQL. Na kolokwium możesz też użyć SSMS GUI.

Zadanie 1 (1 pkt) – Baza Model

Polecenie: Spraw, aby każda nowo tworzona baza danych automatycznie posiadała tabelę pracownicy z kolumnami: Id (INT, PK, IDENTITY), Imie (VARCHAR(50)), Nazwisko (VARCHAR(50)), Dzial (VARCHAR(100)).

Rozwiązanie
USE model; CREATE TABLE dbo.pracownicy ( Id INT PRIMARY KEY IDENTITY(1,1), Imie VARCHAR(50), Nazwisko VARCHAR(50), Dzial VARCHAR(100) ); -- Weryfikacja: CREATE DATABASE TestKolokwium; USE TestKolokwium; SELECT * FROM dbo.pracownicy; -- tabela istnieje!

Zadanie 2 (2 pkt) – Indeksy

Polecenie: Poniższe zapytanie jest bardzo wolne. Zbadaj plan wykonania i zaproponuj indeks(y), które istotnie poprawią wydajność:

SELECT p.Nazwisko, z.DataZamowienia, z.Kwota FROM Zamowienia z JOIN Pracownicy p ON z.PracownikId = p.Id WHERE z.DataZamowienia > '2024-01-01' ORDER BY z.DataZamowienia;

Rozwiązanie
-- 1. Włącz plan: Ctrl+M w SSMS, uruchom zapytanie -- 2. Widzisz: Table Scan na Zamowienia, Nested Loops -- 3. Clustered na DataZamowienia (filtrowanie + ORDER BY) CREATE CLUSTERED INDEX CX_Zam_Data ON dbo.Zamowienia (DataZamowienia); -- 4. Non-clustered covering na klucz obcy CREATE NONCLUSTERED INDEX IX_Zam_Prac ON dbo.Zamowienia (PracownikId) INCLUDE (DataZamowienia, Kwota); -- 5. Ponownie uruchom → Index Seek zamiast Table Scan -- Uzasadnienie: Clustered na DataZamowienia obsługuje -- filtrowanie WHERE i ORDER BY na zakresie dat. -- INCLUDE eliminuje Key Lookup (covering strategy).

Zadanie 3 (2 pkt) – Transakcje

Polecenie: Tabela Produkty: Id=1, Cena=100. Obie sesje: READ COMMITTED, autocommit ON. Odtwórz kroki i podaj wynik każdego SELECTa.

KrokSesja ASesja B
1BEGIN TRAN
2UPDATE Produkty SET Cena=200 WHERE Id=1
3SELECT Cena FROM Produkty WHERE Id=1
4ROLLBACK
5SELECT Cena FROM Produkty WHERE Id=1
Rozwiązanie
-- Krok 1: A otwiera transakcję -- Krok 2: A stawia X lock na wiersz Id=1, Cena=200 (niezacommitowane) -- Krok 3: B próbuje SELECT → READ COMMITTED nie pozwala czytać niezacommitowanych → B CZEKA (blokada!) -- Krok 4: A robi ROLLBACK → Cena wraca do 100, X lock zwolniony -- Krok 5: B się odblokował → B zwraca: Cena = 100 B ponownie SELECT → zwraca: Cena = 100 Odpowiedź: Krok 3 = BLOKADA (czeka). Krok 5 = 100.

Zadanie 4 (2 pkt) – Bezpieczeństwo

Polecenie: W bazie Northwind: utwórz login SQL „student_test" z hasłem „Abc!1234", zmapuj go do usera, utwórz schemat „raport", przenieś tabelę Employees do schematu raport, nadaj userowi SELECT na schemacie, zablokuj UPDATE. Wykaż Access Denied przy próbie UPDATE.

Rozwiązanie
CREATE LOGIN student_test WITH PASSWORD = 'Abc!1234'; USE Northwind; CREATE USER student_test FOR LOGIN student_test; CREATE SCHEMA raport; ALTER SCHEMA raport TRANSFER dbo.Employees; GRANT SELECT ON SCHEMA::raport TO student_test; DENY UPDATE ON SCHEMA::raport TO student_test; -- TEST (połącz się jako student_test): -- SELECT * FROM raport.Employees; → ✅ -- UPDATE raport.Employees SET LastName='X' WHERE EmployeeId=1; → ❌

Zadanie 5 (2 pkt) – Backup & Restore

Polecenie: Na FTP masz 4 pliki: Full_niedzielny.bak, Diff_sroda.bak, Log_czwartek.trn, Log_piatek.trn. Odtwórz bazę do najnowszego stanu. Podaj wynik: SELECT COUNT(*) FROM dbo.Zamowienia;

Rozwiązanie
-- Kolejność: Full → Diff → Log1 → Log2 (ostatni z RECOVERY) RESTORE DATABASE [Zad5] FROM DISK = 'C:\FTP\Full_niedzielny.bak' WITH NORECOVERY, REPLACE; RESTORE DATABASE [Zad5] FROM DISK = 'C:\FTP\Diff_sroda.bak' WITH NORECOVERY; RESTORE LOG [Zad5] FROM DISK = 'C:\FTP\Log_czwartek.trn' WITH NORECOVERY; RESTORE LOG [Zad5] FROM DISK = 'C:\FTP\Log_piatek.trn' WITH RECOVERY; USE [Zad5]; SELECT COUNT(*) FROM dbo.Zamowienia; -- Przepisz wynik na kartkę!

Zadanie 6 (1 pkt) – Maintenance Plan

Polecenie: Utwórz plan konserwacji, który codziennie o godz. 3:00 wykona pełny backup bazy Northwind do katalogu D:\Backup\.

Rozwiązanie (SSMS jest prostsze – użyj Wizarda!)
-- SSMS: Management → Maintenance Plans → Wizard -- 1. Nazwa: „NocnyBackupNorthwind" -- 2. Schedule: codziennie, 3:00 AM -- 3. Zadanie: Back Up Database (Full) -- 4. Baza: Northwind -- 5. Folder: D:\Backup\ -- 6. Finish -- Alternatywnie jako Job (T-SQL): EXEC msdb.dbo.sp_add_job @job_name='MP_Northwind'; EXEC msdb.dbo.sp_add_jobstep @job_name='MP_Northwind', @step_name='FullBackup', @subsystem='TSQL', @command='BACKUP DATABASE [Northwind] TO DISK=''D:\Backup\Northwind_Full.bak'' WITH INIT, COMPRESSION'; EXEC msdb.dbo.sp_add_schedule @schedule_name='Daily3AM', @freq_type=4, @active_start_time=030000; EXEC msdb.dbo.sp_attach_schedule @job_name='MP_Northwind', @schedule_name='Daily3AM'; EXEC msdb.dbo.sp_add_jobserver @job_name='MP_Northwind';

⌨️ Skróty klawiszowe

Szukaj w notatkach
CtrlK
Następny rozdział
Poprzedni rozdział
Zamknij modal
Esc
Skróty klawiszowe
?