Lista zamówień otwiera się kilkanaście sekund. Pracownicy ponawiają kliknięcia, raport zatrzymuje pracę biura, a pierwsza propozycja brzmi: „kupmy mocniejszy serwer”. Czasem to właściwa decyzja. Czasem droższa maszyna będzie jedynie szybciej wykonywać niepotrzebną pracę.
Przed zmianą infrastruktury warto ustalić, gdzie naprawdę znika czas: w bazie danych, w kodzie aplikacji, podczas przesyłania odpowiedzi czy dopiero przy wyświetlaniu tabeli. Poniżej opisuję sposób podejmowania tej decyzji, ze szczegółami dla aplikacji korzystających z Microsoft SQL Server. Przykład jest hipotetyczny, nie stanowi opisu realizacji Inkluzji.
Najpierw zmierz jedną czynność od kliknięcia do wyniku
„System jest wolny” to ważny sygnał, ale za mało, żeby wybrać naprawę. Lepszy opis brzmi: „otwarcie listy zamówień klienta z ostatniego miesiąca trwa długo, zwłaszcza gdy druga osoba uruchamia eksport”. Wtedy można odtworzyć konkretny scenariusz.
Programista powinien powiązać pomiary tego samego żądania: czasu obsługi w aplikacji, wywołań bazy, rozmiaru odpowiedzi oraz pracy interfejsu. Pomaga identyfikator żądania — wspólny numer w logach pozwalający prześledzić jedną operację. Nie trzeba w tym celu zapisywać całej treści dokumentów ani danych klientów.
Hipotetyczny przykład: ekran pojawia się po 12 sekundach, ale zapytanie do bazy trwa 0,2 sekundy. W takiej sytuacji dodanie indeksu nie rozwiąże dominującej części problemu. Trzeba sprawdzić resztę drogi: liczbę dalszych wywołań, generowanie odpowiedzi, sieć i rysowanie tabeli. Nie należy też mechanicznie sumować czasów czynności, które wykonują się równolegle.
Cztery podobne objawy, cztery różne diagnozy
1. Baza odczytuje za dużo danych
Indeks to dodatkowa struktura pomagająca odnaleźć rekordy bez przeglądania całego zbioru. Odpowiednio dobrany może ograniczyć pracę potrzebną do wyszukania zamówień jednego klienta. Nie jest jednak darmowy: zajmuje miejsce i wymaga aktualizacji przy zmianach danych. Nadmiar indeksów może pogorszyć zapis. Dlatego projektuje się je pod konkretne zapytania i cały profil pracy, a nie pod zasadę „więcej znaczy szybciej”. Dokumentacja projektowania indeksów Microsoft opisuje te kompromisy.
2. Aplikacja pyta bazę wiele razy o drobiazgi
Załóżmy, że program pobiera 100 zamówień, a następnie osobno dla każdego odczytuje nazwę klienta. Powstaje 101 wywołań zamiast jednego lub kilku. To wzorzec nazywany N+1. Nawet krótkie zapytania mogą wtedy tworzyć długi czas oczekiwania, szczególnie po przeniesieniu bazy do innej lokalizacji.
Rozwiązaniem może być połączenie danych w jednym zapytaniu albo pobranie potrzebnych informacji partią. Trzeba jednak kontrolować wynik: nieprzemyślane łączenie zamówień, pozycji i płatności może zwielokrotnić wiersze. Mniej wywołań to środek do celu, nie cel sam w sobie.
3. Jedna operacja czeka na drugą
Transakcja łączy powiązane zmiany w jedną całość. W trakcie pracy może utrzymywać blokady, które chronią dane przed kolidującymi operacjami. Krótkie oczekiwanie jest normalne; długa blokada może zatrzymać użytkowników mimo niewielkiego obciążenia procesora.
Przykładowo zapis dokumentu nie powinien bez potrzeby trzymać otwartej transakcji podczas oczekiwania na odpowiedź zewnętrznego systemu. Diagnostyka musi znaleźć początek łańcucha blokad oraz powód, dla którego transakcja się nie kończy. Microsoft opisuje rozpoznawanie i usuwanie blokowania. Zwiększenie limitu czasu oczekiwania jedynie pozwala czekać dłużej — nie usuwa przyczyny.
4. Baza skończyła, ale ekran nadal pracuje
Jeżeli użytkownik potrzebuje pierwszych 50 zamówień, pobieranie całej wieloletniej historii jest podejrzane. Warto rozważyć filtrowanie, sortowanie i stronicowanie po stronie serwera, czyli pobieranie tylko potrzebnego fragmentu. Osobnego pomiaru wymaga liczenie wszystkich pasujących rekordów: nawet mała strona wyników może mieć kosztowny licznik.
Eksport pełnej historii to inny scenariusz niż otwarcie listy. Duży eksport można przygotowywać w tle i udostępniać po zakończeniu. To poprawia sposób pracy użytkownika, ale samo przeniesienie zadania do tła nie zmniejsza kosztu zapytania. Potrzebne są także limity współbieżności i obsługa błędów.

Przykład dla dociekliwych: lista zamówień w SQL Server
Załóżmy tabelę dbo.Orders, unikalne OrderId, identyfikator klienta typu int i datę zamówienia typu datetime2. Poniższy przykład zwraca pierwszą stronę zamówień klienta z określonego przedziału. Nazwy i typy są demonstracyjne; kod wymaga dostosowania do rzeczywistego modelu.
DECLARE @CustomerId int = 42;
DECLARE @From datetime2 = '20260101';
DECLARE @To datetime2 = '20260201';
SELECT TOP (50)
OrderId, OrderDate, Status, Total
FROM dbo.Orders
WHERE CustomerId = @CustomerId
AND OrderDate >= @From
AND OrderDate < @To
ORDER BY OrderDate DESC, OrderId DESC;
Przedział jest domknięty na początku i otwarty na końcu: obejmuje styczeń bez zgadywania ostatniego ułamka sekundy miesiąca. Dodatkowe sortowanie po unikalnym identyfikatorze rozstrzyga kolejność zamówień z taką samą datą. To pierwsza strona; obsługę następnych trzeba zaprojektować osobno, z uwzględnieniem zmian danych podczas przeglądania.
W aplikacji wartości należy przekazać jako parametry sterownika, o typach zgodnych z kolumnami. Deklaracje powyżej służą pokazaniu kompletnego przykładu w narzędziu SQL.
Kandydat do przetestowania dla takiego sposobu wyszukiwania wygląda następująco:
CREATE INDEX IX_Orders_Customer_Date_Id
ON dbo.Orders (CustomerId, OrderDate DESC, OrderId DESC)
INCLUDE (Status, Total);
Kolejność kluczy odpowiada filtrowaniu po kliencie i dacie oraz sortowaniu. Kolumny w INCLUDE przechowują dodatkowe dane potrzebne wynikowi. Nie jest to uniwersalna recepta: najpierw trzeba sprawdzić istniejące indeksy, rozkład danych, częstotliwość zapisów i rzeczywisty plan. Budowę indeksu należy zaplanować z uwzględnieniem obciążenia i blokowania. Sam widok operatora „Scan” również nie dowodzi błędu — przy odczycie dużej części tabeli skanowanie może być właściwe.
Jak udowodnić poprawę zamiast pokazać jeden szybki test
Rzeczywisty plan wykonania pokazuje, jak SQL Server wykonał zapytanie, wraz z informacjami z uruchomienia. Pozwala sprawdzić między innymi rozbieżności między przewidywaną a faktyczną liczbą wierszy. Jego uzyskanie wymaga wykonania zapytania — kosztownych operacji nie należy uruchamiać bez namysłu na produkcji. Instrukcja Microsoft opisuje wymagane uprawnienia i sposób odczytu planu.
SET STATISTICS IO ON pozwala zobaczyć między innymi odczyty logiczne, czyli liczbę odczytanych stron z pamięci podręcznej danych. Mniej takich odczytów może wskazywać ograniczenie pracy zapytania, ale nie jest samodzielnym dowodem, że cały ekran działa szybciej. Znaczenie liczników opisuje dokumentacja STATISTICS IO.
Query Store przechowuje historię zapytań, planów i zagregowanych statystyk wykonania. Pomaga porównać zachowanie przed i po zmianie oraz znaleźć pogorszenie związane z innym planem. Nie zastępuje jednak pomiaru czasu widzianego przez użytkownika. W SQL Server 2017 i 2019 nie jest domyślnie włączony; od SQL Server 2022 jest domyślnie włączony dla nowych baz. Dla konkretnej bazy trzeba sprawdzić stan, limit miejsca i zasady zbierania danych. Opis Query Store w Microsoft Learn.
Test odbiorowy powinien obejmować:
- ten sam scenariusz, porównywalny zbiór danych i kilku użytkowników jednocześnie;
- typowego klienta oraz klienta z wyjątkowo dużą historią;
- czas całej operacji, liczbę wywołań bazy i wielkość odpowiedzi;
- zgodność wyników: filtry, kolejność, kompletność i uprawnienia;
- wpływ zmiany na zapis danych, raporty i inne ważne ekrany.
Warto porównywać medianę oraz p95 — czas, w którym mieści się około 95% zmierzonych operacji. Sam średni wynik potrafi ukryć grupę bardzo wolnych żądań. Progi odbioru należy uzgodnić przed pracą, a pomiar powtórzyć po wdrożeniu w reprezentatywnym okresie.
Kiedy większy serwer ma sens?
Gdy pomiary pokazują rzeczywisty niedobór zasobów przy uzasadnionym obciążeniu: procesora, pamięci albo wydajności dysków. Najpierw trzeba jednak powiązać ten niedobór z wolną operacją. Sam wysoki procent wykorzystania pamięci przez bazę nie wystarcza do diagnozy.
Praktyczna decyzja uwzględnia koszt pracy programisty, koszt utrzymania infrastruktury i pilność problemu. Doraźne zwiększenie zasobów może być rozsądnym sposobem przywrócenia sprawności firmy, równolegle z analizą przyczyny. Powinno mieć mierzalny efekt i termin oceny. „Serwer jest teraz większy” nie jest kryterium odbioru; „pracownik może sprawnie wyszukać i zapisać dokument w godzinach szczytu” już nim jest.
Co przygotować do rozmowy z programistą?
Wystarczy nazwa wolnej czynności, moment wystąpienia, przybliżona liczba użytkowników, skala danych oraz informacja, od kiedy problem się pojawia. Szczególnie przydatne jest rozróżnienie: wszyscy czy jedna osoba, każdy klient czy tylko duże kartoteki, zawsze czy podczas importu. Nie trzeba samodzielnie diagnozować indeksów.
Jeżeli problem obejmuje wymianę danych między systemami, zobacz także dlaczego integracje tworzą duplikaty i jak temu zapobiegać. Szybkość oraz poprawność to dwa osobne warunki dobrego rozwiązania.
Zakres prac nad aplikacjami i bazami danych znajdziesz na stronie Inkluzji. Dobrym punktem wyjścia do zlecenia jest jedna konkretna, odtwarzalna operacja oraz uzgodniony sposób pomiaru. To pozwala ocenić rezultat, zamiast finansować serię domysłów.
Źródła techniczne: dokumentacja Microsoft podlinkowana przy odpowiednich zagadnieniach; sprawdzona 27 października 2026 r. Zdjęcie główne: Taylor Vick / Unsplash. Zdjęcie w treści: Chris Ried / Unsplash. Oba zdjęcia poglądowe wykorzystano na licencji Unsplash; nie dokumentują infrastruktury ani realizacji Inkluzji.
