Bazy danych

Baza pytań rekrutacyjnych i wiedzy. Filtruj, szukaj i sprawdzaj swoją wiedzę.

Tematy
mediumhibernateormperformance+1

Odpowiedź

Problem N+1 występuje, gdy Hibernate pobiera N encji nadrzędnych jednym zapytaniem, a następnie leniwie dociąga dzieci osobnym zapytaniem dla każdej encji, co daje N dodatkowych selectów. Rozwiązania to fetch joiny/entity graphy, batch fetching lub zmiana strategii pobierania.

mediumtransactionaciddatabase-theory

Odpowiedź

ACID opisuje gwarancje transakcji: Atomicity (wszystko albo nic), Consistency (zachowanie niezmienników), Isolation (transakcje współbieżne zachowują się jak wykonywane sekwencyjnie) oraz Durability (zatwierdzone dane przetrwają awarię).

hardindexingb-treehash+1

Odpowiedź

Indeksy B‑tree utrzymują klucze w porządku, więc dobrze wspierają wyszukiwanie równościowe, zakresy, prefiksy i ORDER BY. Indeksy hash mapują klucze do kubełków i są szybkie dla równości, ale nie obsługują zakresów ani sortowania.

hardnormalizationdatabase-designtheory

Odpowiedź

Normalizacja zmniejsza redundancję danych. 1NF wymaga atomowych kolumn i braku grup powtarzalnych. 2NF to 1NF oraz zależność atrybutów nie‑kluczowych od całego klucza. 3NF to 2NF bez zależności przechodnich między atrybutami nie‑kluczowymi.

mediumsqlnosqlcomparison+1

Odpowiedź

Bazy SQL są relacyjne, mają z góry zdefiniowany schemat, joiny i silne transakcje ACID. Bazy NoSQL są nierelacyjne (dokumentowe, key‑value, kolumnowe, grafowe), zwykle mają elastyczny schemat i łatwiej się skalują horyzontalnie, czasem kosztem ścisłej spójności.

Odpowiedź

Primary key jednoznacznie identyfikuje wiersz (i może być referencjonowany przez FK). Unique constraint też wymusza unikalność, ale nie musi być „tożsamością” wiersza. Indeks to struktura przyspieszająca odczyty; może być unikalny lub nie.

easytransactionacidconsistency

Odpowiedź

Transakcja łączy wiele operacji w jedną jednostkę pracy: albo wszystkie się udają, albo następuje rollback. Chroni spójność danych, szczególnie przy współbieżności i awariach.

Odpowiedź

Indeks przyspiesza odczyty (filtrowanie/sortowanie), bo unika pełnych skanów tabeli. Trade-off to wolniejsze zapisy (INSERT/UPDATE/DELETE) i dodatkowe miejsce, bo indeks trzeba utrzymywać.

Odpowiedź

INNER JOIN zwraca tylko wiersze pasujące w obu tabelach. LEFT JOIN zwraca wszystkie wiersze z lewej tabeli i uzupełnia brakujące dopasowania z prawej strony NULLami.

SELECT u.id, p.id
FROM users u
LEFT JOIN posts p ON p.user_id = u.id;
mediumnormalizationdenormalizationschema-design

Odpowiedź

Normalizacja zmniejsza redundancję i anomalie aktualizacji przez podział danych na powiązane tabele. Denormalizacja duplikuje część danych, żeby przyspieszyć odczyty i ograniczyć joiny, kosztem trudniejszych zapisów i pilnowania spójności.

mediumtransactionsisolationconcurrency

Odpowiedź

Izolacja definiuje, jakie anomalie są dopuszczalne przy współbieżnych transakcjach (dirty/non-repeatable reads, phantoms). Wyższa izolacja daje większą poprawność, ale może zmniejszać współbieżność i wydajność.

hardn-plus-oneormperformance

Odpowiedź

To sytuacja, gdy pobierasz N rekordów nadrzędnych i potem odpalasz po jednym dodatkowym zapytaniu na każdy (czyli N zapytań więcej). Unikasz przez joiny, batching, prefetch/eager loading albo zapytania typu `IN (...)`.

Odpowiedź

Optimistic locking zakłada rzadkie konflikty: aktualizujesz z kontrolą wersji/timestamp i robisz retry przy konflikcie. Pessimistic locking blokuje wiersze z góry (np. `SELECT ... FOR UPDATE`), żeby inni nie mogli ich zmienić.

SELECT *
FROM accounts
WHERE id = 1
FOR UPDATE;

Odpowiedź

Replikacja kopiuje te same dane na wiele węzłów (lepsza skala odczytu i dostępność). Sharding dzieli dane między węzłami (lepsza skala zapisu/rozmiaru), ale komplikuje zapytania i transakcje.

hardexplainquery-planperformance

Odpowiedź

Najpierw patrz na węzły z największym kosztem/czasem oraz typ skanu (Seq Scan vs Index Scan) i estymacje wierszy. Potem sprawdź joiny/sortowanie i czy indeksy są używane; poprawiasz zapytanie, indeksy lub statystyki.

easyforeign-keyconstraintsintegrity

Odpowiedź

Foreign key to constraint łączący kolumnę z kluczem primary/unique w innej tabeli. Wymusza integralność referencyjną: nie możesz wskazać wiersza, który nie istnieje (i może kontrolować zachowanie przy delete/update).

Odpowiedź

GROUP BY grupuje wiersze do agregacji. HAVING filtruje grupy po agregacji (a WHERE filtruje wiersze przed grupowaniem). Np. „tylko grupy z count > 10”.

SELECT country, COUNT(*) AS cnt
FROM users
GROUP BY country
HAVING COUNT(*) > 10;
mediumindexcovering-indexperformance

Odpowiedź

Covering index zawiera wszystkie kolumny potrzebne do zapytania, więc baza potrafi odpowiedzieć używając tylko indeksu (bez sięgania do tabeli). Może mocno przyspieszyć odczyty kosztem większych indeksów i wolniejszych zapisów.

harddeadlocklockingtransactions+1

Odpowiedź

Deadlock to sytuacja, gdy transakcje czekają na swoje blokady w cyklu i żadna nie może ruszyć dalej. Ograniczasz przez krótkie transakcje, spójny porządek blokowania i retry przy błędach deadlock.

hardsql-injectionsecurityprepared-statements

Odpowiedź

SQL injection to sytuacja, gdy nieufny input zmienia znaczenie SQL (np. przez konkatenację stringów). Zapobiegasz przez zapytania parametryzowane/prepared statements, poprawne escapowanie przez driver/ORM i konta DB z minimalnymi uprawnieniami.

Odpowiedź

Indeks złożony indeksuje kilka kolumn razem (np. (org_id, email)). Pomaga, gdy zapytania filtrują/sortują po lewym prefiksie tych kolumn, zmniejszając skany i przyspieszając wyszukiwanie.

mediumsqlwindow-functionsrow_number

Odpowiedź

Window function liczy wartość na „oknie” wierszy powiązanych z bieżącym wierszem, bez zwijania wierszy jak GROUP BY. Use case: ranking (ROW_NUMBER), sumy narastające, „top N per grupa”.

SELECT user_id,
       amount,
       ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS rn
FROM payments;

Odpowiedź

Constrainty (PK, FK, UNIQUE, CHECK) to deklaratywne reguły egzekwowane przez silnik bazy. Triggery to własny kod uruchamiany przy zdarzeniach. Jeśli się da, preferuj constrainty do integralności, bo są prostsze, przewidywalne i zoptymalizowane.

hardidempotencyunique-constraintupsert+1

Odpowiedź

Użyj unique constraint na idempotency key (albo naturalnym kluczu) i zrób upsert/insert z obsługą konfliktu. Jeśli ten sam request przyjdzie drugi raz, zapis stanie się no-opem albo zaktualizuje ten sam wiersz zamiast tworzyć duplikat.

hardsoft-deletedata-retentionauditing

Odpowiedź

Soft delete oznacza oznaczenie rekordu jako usunięty (np. `deleted_at`), co pozwala na przywracanie/audyt, ale komplikuje zapytania i indeksy (trzeba filtrować usunięte). Hard delete usuwa dane i upraszcza zapytania, ale tracisz historię, jeśli jej nie archiwizujesz.

Odpowiedź

`SELECT *` pobiera więcej danych niż potrzeba (więcej I/O i pamięci) i mocno wiąże kod ze zmianami schematu (dodanie kolumny może zmienić wynik, rozmiar payloadu albo ujawnić wrażliwe pola). Wybieranie tylko potrzebnych kolumn jest czytelniejsze i może umożliwić lepsze plany (np. index-only).

Odpowiedź

NULL oznacza “nieznane”, więc porównania typu `col = NULL` dają UNKNOWN, a nie true/false (logika trójwartościowa). Użyj `IS NULL` / `IS NOT NULL`, a w niektórych bazach `IS DISTINCT FROM`, żeby bezpiecznie porównywać z NULL.

mediumscalingpartitioningsharding+1

Odpowiedź

Partycjonowanie dzieli jedną logiczną tabelę na mniejsze części, zwykle w ramach jednego systemu bazy (ułatwia zarządzanie i może przyspieszać zapytania przez pruning). Sharding dzieli dane na wiele instancji/nodów bazy, żeby skalować poziomo. Partycjonowanie jest zwykle prostsze; sharding dokłada złożoność rozproszoną.

hardviewsmaterialized-viewperformance+1

Odpowiedź

Materialized view fizycznie przechowuje wynik zapytania, więc odczyt może być dużo szybszy niż liczenie tego za każdym razem. Ma sens przy drogich agregacjach lub raportowaniu, akceptując trade-off: koszt odświeżania i (często) lekko nieaktualne dane.

Odpowiedź

Write amplification oznacza, że jeden logiczny zapis powoduje wiele zapisów fizycznych: wiersz w tabeli plus każdy indeks, którego dotyczy zmiana (często także WAL/redo logi). Więcej indeksów zwykle przyspiesza odczyty, ale spowalnia insert/update/delete oraz zwiększa koszt miejsca i utrzymania.

Odpowiedź

Selektywność to informacja, jak dobrze kolumna filtruje wiersze (ile wierszy pasuje do warunku). Indeks o wysokiej selektywności (mało dopasowań) jest bardziej użyteczny, bo baza omija skanowanie dużej liczby wierszy. Kolumny o niskiej selektywności (np. boolean) często niewiele zyskują z samego indeksu.

Odpowiedź

Optymalizator wybiera plan na podstawie estymacji liczby wierszy (cardinality). Jeśli estymacje są złe (stare statystyki, nierówny rozkład danych, skorelowane kolumny), może wybrać złą kolejność joinów albo zły algorytm. Aktualne statystyki (np. ANALYZE) i odpowiednie indeksy pomagają mu lepiej estymować.

Odpowiedź

Wildcard na początku (`%term`) często uniemożliwia użycie zwykłego indeksu B-tree, więc baza może skanować dużo wierszy. Alternatywy to indeksy full-text, trigramy (jeśli baza wspiera) albo zmiana zapytania na wyszukiwanie po prefiksie (`term%`), jeśli to możliwe.

Odpowiedź

Użyj podejścia expand/contract: dodaj nową kolumnę, zrób backfill partiami, zapisuj do obu (albo utrzymuj spójność), przełącz odczyt na nową kolumnę, a na końcu usuń starą. Dzięki temu unikasz długich blokujących locków i wdrażasz zmianę bezpiecznie.

Odpowiedź

Długie transakcje mogą długo trzymać locki, blokować inne zapytania i zwiększać contention. W bazach MVCC mogą też blokować sprzątanie starych wersji wierszy, co prowadzi do bloatu. Mogą też zwiększać replication lag i utrudniać recovery po awarii.

easydatabaseconstraintsprimary-key+1

Odpowiedź

Primary key jednoznacznie identyfikuje wiersz i zwykle oznacza NOT NULL oraz jeden główny identyfikator na tabelę. Unique constraint także wymusza unikalność, ale możesz mieć ich wiele i w zależności od bazy mogą dopuszczać NULL.

Odpowiedź

Klucze obce wymuszają spójność referencyjną (brak sierot) i ułatwiają reasoning. Trade‑off to dodatkowy koszt zapisu i czasem trudniejsze migracje. W bardzo obciążonych systemach część zespołów waliduje relacje w aplikacji zamiast w bazie.

Odpowiedź

Większość baz używa zasady left‑most prefix. Indeks na (A, B, C) przyspiesza zapytania po A lub A,B, ale nie po samym B. Kolejność dobieraj według typowych filtrów i selektywności.

Odpowiedź

Covering index zawiera wszystkie kolumny potrzebne do zapytania, więc baza może odpowiedzieć, używając tylko indeksu bez odczytu wierszy z tabeli. To zmniejsza I/O i bywa dużo szybsze na dużych tabelach.

mediumdatabasetransactionslocks+1

Odpowiedź

Deadlock występuje, gdy dwie transakcje czekają na swoje wzajemne locki. Baza wykrywa to i przerywa (rollback) jedną transakcję, aby druga mogła ruszyć. Aplikacja powinna ponowić przerwaną transakcję.

Odpowiedź

Read Committed blokuje brudne odczyty, ale dopuszcza non‑repeatable reads. Repeatable Read gwarantuje, że odczytane wiersze się nie zmienią w trakcie transakcji, ale może dopuścić phantom rows. Serializable jest najsurowszy — zachowuje się jakby transakcje działały po kolei, eliminując phantom, kosztem mniejszej współbieżności.

harddatabasepartitioningsharding+1

Odpowiedź

Partitioning dzieli tabelę na części w obrębie jednej instancji bazy (często dla zarządzania/wydajności). Sharding dzieli dane między wiele serwerów baz danych dla skalowania poziomego. Sharding dodaje złożoność w routingu i zapytaniach między shardami.

Odpowiedź

Denormalizacja polega na duplikacji danych, aby przyspieszyć odczyt i ograniczyć joiny. Pomaga w read‑heavy workloadach, ale zwiększa storage, ryzyko niespójności oraz komplikuje zapisy i migracje.

Odpowiedź

OLTP obsługuje wiele małych, krótkich transakcji (workload operacyjny). OLAP wykonuje mniej, ale cięższych zapytań analitycznych na dużych zbiorach (raporty/BI). Różni się projekt schematu, indeksowanie i storage.

easydatabasetransactionsautocommit+1

Odpowiedź

W autocommit każdy statement jest osobną transakcją. Transakcje jawne grupują wiele statementów w jedną atomową całość, co ma znaczenie dla spójności i wydajności (mniej commitów/round‑tripów). Używaj jawnych transakcji przy wieloetapowych zmianach, które muszą się udać lub wycofać razem.