Skalowanie bazy danych w sklepie B2B - replikacja, sharding, read replicas
Większość problemów wydajnościowych „bazy danych" w sklepach B2B nie jest problemem bazy. Jest problemem braku cache, źle napisanych zapytań N+1, lub indeksów. Skalowanie bazy (replikacja, read replicas, sharding) to **ostatnie** narzędzie, nie pierwsze. Najpierw napraw to, co masz. Potem dodaj cache. Dopiero potem skaluj DB.
Spis treści (9)
W skrócie
- 1. Pierwsze kroki przed skalowaniem: profile slow query log, dodaj brakujące indeksy, napraw N+1, dodaj Redis cache
- 2. Master-slave replication: read replicas dla raportów i powtarzalnych queries
- 3. Percona / MariaDB zamiast MySQL: marginalne zyski performance + lepsze tooling
- 4. Sharding: rzadko sensowne w polskim B2B - koszt operacyjny wysoki
- 5. PostgreSQL zamiast MySQL: dla projektów z dużą logiką JSON / analytics
Najpierw zoptymalizuj, dopiero potem skaluj
Sklep „wolny" zazwyczaj nie potrzebuje większej bazy. Potrzebuje:
1. Slow query log. MySQL slow_query_log → long_query_time = 1 → przeglądanie zapytań > 1s. Najczęściej znajdziesz 5-10 zapytań do refaktoru.
2. Brakujące indeksy. Każdy WHERE / JOIN po kolumnie bez indeksu = full table scan. EXPLAIN każdej powolnej query.
3. N+1 queries. Klasyczny problem ORM. Lista 50 produktów → 51 queries (1 dla listy + 50 per produkt po kategorię/atrybuty). Eager loading rozwiązuje.
4. Cache. Jeśli wciąż ta sama query wykonywana 100×/min - cache w Redis. Cache warstwy.
5. Search dedykowany. Filtry i search z MySQL przy 30k+ SKU = bottleneck. Elastic. Search.
Te 5 kroków rozwiązuje 80% problemów wydajnościowych „bazy" w średnich sklepach B2B. Bez kosztownego skalowania.
Pionowa skalowalność (większy serwer)
Najprostsze. Większa maszyna = więcej CPU/RAM/IO. Większość polskich B2B działa na 1-2 maszynach DB.
Konfiguracja typowa dla średniego sklepu:
- Magento 2.4 + Comarch XL integracja
- 50k SKU, 200 kontrahentów, 5k zamówień/mies.
- Maszyna: 16-32 CPU cores, 64-128 GB RAM, NVMe 1-2 TB
- Hetzner / OVH / dedykowane: 2-5 tys. zł / mies.
To wystarcza często do 100 M zł obrotu rocznego. Dopiero powyżej rozważasz skalowanie poziome.
Tuning MySQL/MariaDB dla sklepu:
innodb_buffer_pool_size = 70-80% RAM
innodb_log_file_size = 512MB-1GB
innodb_flush_log_at_trx_commit = 2 (kompromis między bezpieczeństwem a wydajnością)
innodb_io_capacity = 2000-10000 (zależnie od dysku)
max_connections = 500-1000
To są typowe wartości startowe. Tuning per workload przy pomocy mysqltuner lub pt-mysql-summary.
Master-slave replication
Pierwsze poziome skalowanie. Master przyjmuje zapisy, slaves obsługują odczyty.
Architektura:
[Application]
|
+--- Master (writes + niektóre reads) <----- MySQL Binary Log Replication
|
+--- Slave 1 (reads - operacyjne)
+--- Slave 2 (reads - raporty/BI)
Co skierować na slave:
- Listy produktów (PLP) dla niezalogowanych
- Wyszukiwanie produktów
- Strony kategorii
- Strony statyczne (CMS)
- Raporty i analytics (osobny slave dedykowany)
Co zostaje na master:
- Operacje na koszyku
- Składanie zamówień
- Panel klienta / admin
- Dane zmienne (sesje, locki)
Implementacja w Magento:
- Magento ma wbudowane wsparcie dla split databases (settings.xml / env.php)
- Można zdefiniować osobne connections dla różnych obszarów (catalog vs. checkout)
Implementacja w Shopware / custom:
- Doctrine connections (multi-master/slave)
- Aplikacja decyduje per query (przez Read/Write split w ORM)
Realne wykonanie:
- 1 master + 2 slaves dla średniego sklepu = ~2× pojemność read
- Replication lag <1s dla większości scenariuszy
- Trzeba pamiętać o async - w niektórych scenariuszach (np. zaraz po INSERT, SELECT na slave) - eventual consistency
Read replicas dla raportów
Osobny pattern, gdzie slave dedykowany jest tylko dla raportowych queries (BI, dashboardy, analytics):
- Raporty robione na własnym slave
- Slave może być nawet z opóźnieniem 5-15 min
- Operacyjne queries nie obciążane raportami
To rozwiązuje problem klasyczny: raport „top 100 produktów ostatniego kwartału" wykonywany w godzinach pracy na produkcyjnej bazie wieszczy sklepowy katalog na 30 sekund.
Partycjonowanie tabel
Tabele rosną. sales_order z 5 milionami rekordów. customer_log z 50 milionami.
Partycjonowanie po dacie (najczęstsze dla e-commerce):
- Tabela
sales_orderpartycjonowana pocreated_atper miesiąc - Stare partycje (>2 lata) przenoszone do archiwum
- Queries po dacie automatycznie skanują tylko relevantną partycję
MySQL/MariaDB: PARTITION BY RANGE (YEAR(created_at)*100 + MONTH(created_at))
PostgreSQL: declarative partitioning (od v10+), bardziej elegancko niż MySQL.
Magento: archiving zamówień (>2 lata) do osobnego storage, czyszczenie tabel log/index.
To nie jest sharding (różne maszyny), tylko logiczny podział wewnątrz jednej maszyny. Ale przyspiesza znacznie.
Sharding - gdy naprawdę nie ma wyjścia
Sharding = dzielenie danych na różne maszyny po klucz. Klient A-M na shard 1, N-Z na shard 2.
Problemy:
- Skomplikowane queries (JOIN-y między shardami)
- Migracje (przenoszenie danych między shardami)
- Cross-shard transakcje (distributed transactions = piekło)
- Każde dodanie kolumny / zmiana schema na N shardach
Kiedy sharding:
- Powyżej setek milionów rekordów w głównych tabelach
- Powyżej 10k zapisów/sec
- Wszystkie inne opcje wyczerpane
W polskim B2B średniej skali: prawie nigdy. Sharding ma sens głównie dla globalnych marketplace'ów typu Allegro, eBay.
Alternatywa, lepsza dla większości - microservices z separacją per domain (catalog osobno, customer osobno, orders osobno). Każdy bounded context ma swoją bazę. To naturalna ścieżka.
Percona / MariaDB vs. MySQL
MySQL Community Edition od Oracle. Percona Server for MySQL - drop-in replacement, dodatkowe diagnostyki, lepsza wydajność w niektórych scenariuszach. MariaDB - fork MySQL z 2009, własny rozwój, niektóre funkcje plus.
Praktyczne różnice:
- Percona: lepsza wydajność InnoDB pod wysokim load, tooling (pt-tools)
- MariaDB: większy rozwój własnych funkcji, niektóre features bardziej eleganckie
- MySQL: standardowy, najbardziej zgodny ze wszystkim
Dla nowego sklepu B2B: Percona lub MariaDB > vanilla MySQL. Migracja vanilla → Percona jest bezbolesna.
PostgreSQL - alternatywa
PostgreSQL bywa lepszy dla:
- Analytics queries. Window functions, CTE, partitioning lepsze w PG.
- JSON. JSONB w PG to first-class citizen. W MySQL JSON jest, ale słabszy.
- Geo queries. PostGIS to złoty standard.
- Strict typing. Mniej niespodzianek przy automatycznych konwersjach.
Słabsze strony PG dla e-commerce:
- Mniejsze wsparcie w Magento (Magento jest MySQL-centric)
- Shopware wspiera, ale MySQL jest defaultem
- Mniej deweloperów PG w polskim ekosystemie e-commerce
Dla custom projektów: PostgreSQL warty rozważenia. Dla Magento/Shopware - zostań przy MySQL/MariaDB/Percona.
Backup i recovery
Skalowanie bazy nie wystarczy bez backup'u.
Wymagania:
- Daily full backup
- Hourly incremental backup
- Backup przechowywany off-site (inna lokalizacja, inna chmura)
- Tested recovery - kwartalne testy „czy backup naprawdę odtworzy się"
Narzędzia:
mysqldump- najprostsze, ale powolne dla dużych bazxtrabackup(Percona) - hot backup, szybszemariabackup(MariaDB) - odpowiednik xtrabackup- Snapshots na poziomie storage (jeśli storage to wspiera, np. ZFS, LVM)
RTO i RPO:
- RTO (Recovery Time Objective): ile czasu w razie awarii do przywrócenia. Dla sklepu B2B - 1-4h ok.
- RPO (Recovery Point Objective): ile danych można stracić. Dla sklepu B2B - max 1h (czyli hourly backup).
FAQ
Magento wspiera read replicas? Tak, ma split databases support (catalog / checkout / sales connections osobno). Dodatkowo Adobe Commerce ma lepsze wsparcie niż OS.
Czy mogę używać MongoDB / NoSQL w sklepie B2B? Dla głównej bazy - raczej nie, e-commerce wymaga ACID transakcji (zamówienia). MongoDB ma sens dla logów, analytics, search (czasem zamiast Elastic).
Czy AWS RDS / Aurora są drogie? Tak, kilka razy droższe niż self-hosted MariaDB/Percona na Hetznerze. Aurora ma plusy (auto-scaling, multi-AZ), ale dla polskiego B2B średniej skali - self-hosted ekonomiczniejsze.
Czy ZFS na storage daje przewagę? Snapshots, compression, copy-on-write. Dla baz danych - przewaga, ale wymaga znajomości ZFS-a (niedaleki MySQL DBA tego nie umie out-of-the-box).
Czy mogę używać MariaDB Galera Cluster? Synchronous multi-master replication. Działa, ale kompromis: synchroniczność = wolniejsze zapisy. Dla większości polskich B2B - async master-slave wystarczy.
Co dalej
- Pillar architektury: Architektura dużych sklepów
- Cache (krytyczne PRZED skalowaniem DB): Cache warstwy
- Microservices jako alternatywa shardingu: Monolit vs. microservices
- Wydajność: Wydajność e-commerce
O autorze
Jakub Owsianka
Architekt rozwiązania w WiseB2B - silniku platform B2B. Zaczynał po stronie biznesu (własne sklepy), potem deweloper, dziś projektuje wdrożenia dla sklepów z katalogami w dziesiątkach tysięcy SKU. W ostatnich latach wdrożył AI-development w zespole i funkcjonalności oparte o AI bezpośrednio w silniku sklepu.
Masz pytanie do tego artykułu?
Dodatkowy kontekst, problem z własnym wdrożeniem, druga opinia - napisz wprost. Odpowiadam osobiście w 1-2 dni robocze.