Wolny dziennik zapytań MySQL pokazuje mi w hostingu, które zapytania pochłaniają czas, jak często występują i dlaczego spowalniają działanie. Pokazuję konkretne kroki, jak aktywować dziennik, przeanalizować go i przebudować zapytania, aby strony ładowały się szybciej, a zasoby serwera działały wydajniej.
Punkty centralne
- Aktywacja i rozsądnie ustawić wartości progowe
- Ocena z pt-query-digest i mysqldumpslow
- Metryki interpretować: Query_time, Lock_time, Rows_examined
- Strojenie poprzez indeksy, EXPLAIN i przepisywanie
- Automatyzacja i monitorowanie w hostingu
Co robi dziennik powolnych zapytań w hostingu?
Hosting oznacza współdzielone zasoby, więc liczy się każda milisekunda na zapytanie. Używam dziennika, aby znaleźć zapytania, które działają dłużej niż zdefiniowany limit i zobaczyć kluczowe dane, takie jak Query_time, Lock_time, Rows_sent i Rows_examined dla każdego zapytania. Liczby te pokazują mi, czy za zapytaniem kryje się brakujący indeks, niekorzystne złączenie lub pełne skanowanie tabeli. Zwłaszcza na serwerach z wieloma witrynami pojedyncze złe zapytanie może znacznie obciążyć procesor i wejścia/wyjścia. Następnie ustalam priorytety dla zapytań o najwyższym łącznym czasie, ponieważ to właśnie one mają największy wpływ na czas ładowania i obciążenie serwera.
Aktywacja i rozsądne wartości progowe
StartMogę runtime lub na stałe przez my.cnf, w zależności od dostępu na hostingu. Do szybkich testów włączam log tymczasowo i ustawiam long_query_time na wartość odpowiadającą ruchowi i sprzętowi. Często ustawiam 0,1 sekundy dla intensywnie używanych witryn, ale monitoruję rozmiar dziennika, aby I / O nie rosło niepotrzebnie. Jeśli bezpośredni dostęp do plików jest ograniczony, używam opcji schematu wydajności powłoki MySQL do generowania raportów. Po dostrojeniu zapisuję ostateczne ustawienia w pliku konfiguracyjnym i restartuję usługę.
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';
SET GLOBAL log_queries_not_using_indexes = 'ON';
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
Na stałe Ustawiam opcje takie jak log_throttle_queries_not_using_indexes i log_slow_admin_statements, aby dziennik pozostał użyteczny i nie eksplodował. Dokumentuję każdą wartość, na przykład dlaczego long_query_time wynosi 0,5 lub 0,1 sekundy. Dzięki temu mogę je później dopracować. W środowiskach współdzielonych często omawiam aktywację z dostawcą lub korzystam z jego panelu. Każdą aktywację łączę z datą rozpoczęcia, aby móc czysto porównywać efekty w monitorowaniu i metrykach.
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 1
log_queries_not_using_indexes = 1
log_throttle_queries_not_using_indexes = 10
log_slow_admin_statements = 1
Skuteczna ocena powolnego dziennika
Surowe dane są zaszumione, więc podsumowuję je za pomocą pt-query-digest i sortuję według całkowitego czasu w znaczącym okresie czasu. W ten sposób rozpoznaję wzorce, wysoce zmienne zapytania i rodziny zapytań, które różnią się tylko parametrem. Sprawdzam rozkład, a nie tylko średnią, ponieważ wartości odstające powodują prawdziwe problemy użytkownika. Aby uzyskać szybki przegląd, mysqldumpslow pomaga mi zobaczyć dziesięć najwolniejszych grup. Więcej szczegółów uzyskuję za pomocą okien czasowych, filtrów bazy danych i eksportu do analizy tekstowej.
pt-query-digest /var/log/mysql/slow-query.log
pt-query-digest --since '24h' /var/log/mysql/slow-query.log
mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log
Przydatne to także spojrzenie na inne dzienniki, gdy w grę wchodzą funkcje aplikacji lub PHP. Aby to zrobić, używam istniejących przepływów pracy dziennika i łączę wyniki. Ten przewodnik często stanowi dla mnie wprowadzenie: Analiza dzienników. Synchronizuję znaczniki czasu, aby móc porównywać szczyty ruchu z pikami zapytań. Pozwala mi to sprawdzić, czy pominięcia pamięci podręcznej, zadania cron lub zadania importu korzystają z bazy danych w tym samym czasie.
Prawidłowa interpretacja wskaźników
Query_time pokazuje czysty czas wykonania; w pierwszej kolejności nadaję priorytet zapytaniom powyżej jednej sekundy. Lock_time wskazuje czas oczekiwania z powodu blokad, które często wynikają z niepotrzebnie długich transakcji lub dużych partii. Stosunek Rows_examined do Rows_sent mówi mi, czy zapytania przeglądają zbyt wiele wierszy i czy brakuje indeksów. Jeśli dziennik zawiera wiele wpisów „No index use“, ustawiam dławienie i przyglądam się bliżej tabelom, których to dotyczy. Ważne jest, aby zawsze zajmować się przyczyną, a nie objawem: Indeks na właściwej kolumnie jest lepszy niż jakakolwiek modernizacja sprzętu.
| Metryki | Co widzę | Pomiar |
|---|---|---|
| Query_time high | Długi czas działania na wersję | Sprawdź EXPLAIN, przepisz zapytanie, dodaj indeks |
| Lock_time high | Czas oczekiwania na blokady | Skrócenie transakcji, zmniejszenie rozmiaru partii, odpowiednia izolacja |
| Rows_examined ≫ Rows_sent | Skanował za dużo, zwracał za mało | Kolumny filtrujące indeks, tworzenie skalowalności |
| Nie użyto indeksu | Pełne skanowanie tabeli | Utwórz indeks, unikaj wyrażenia w WHERE |
Wartości graniczne Dostosowuję go po pierwszym tygodniu, aby nie zgubić się w szumie. Obniżam long_query_time etapami, aż uzyskam wystarczającą liczbę trafień do systematycznej poprawy. Każde dostosowanie dokumentuję datą i powodem. Pozwala to skupić się na ocenie. Wartościowe trafienia oszczędzają mi później powielania pracy.
Praktyka: Dostrajanie zapytań krok po kroku
WYJAŚNIENIE jest moim początkiem przed zmianą kodu. Szukam „type: ALL“, „rows“ z dużymi liczbami i „Using filesort“ lub „Using temporary“. Funkcje na kolumnach w WHERE lub JOIN często uniemożliwiają użycie indeksu. Zamiast tego formułuję warunki sargable, a następnie sprawdzam nowy plan. Każdy krok musi wykonać redukcję wierszy wcześnie i celowo.
EXPLAIN SELECT * FROM orders WHERE YEAR(created_at) = 2026;
-- Lepiej:
CREATE INDEX idx_orders_created ON orders(created_at);
SELECT * FROM orders
WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01';
WSPÓLNE Optymalizuję sprawdzając kolejność łączenia i dopasowując indeksy na kluczach łączenia. Sprawdzam, czy indeks złożony obejmuje WHERE + ORDER BY, aby uniknąć sortowania plików. Ustawiam LIMIT tam, gdzie potrzebny jest tylko podgląd. Zapisuję buforowanie wyników na poziomie aplikacji dla powtarzających się, identycznych zapytań o niskim wskaźniku zmian. Bardziej szczegółowe wprowadzenie do indeksów i blokad można znaleźć tutaj: Indeksy i blokady.
Strategie indeksowania dla CMS i sklepów
WordPress, WooCommerce lub systemy sklepowe tworzą typowe wzorce: dużo czytania, selektywne pisanie, często z meta lub tabelami produktów. Analizuję najczęstsze ścieżki - strona główna, kategoria, wyszukiwanie, kasa - i umieszczam indeksy specjalnie na kolumnach filtrowania, sortowania i łączenia. Indeksy obejmujące (np. (status, created_at, id)) oszczędzają wiele odwołań do tabeli. Do wyszukiwania prefiksów używam odpowiednich form indeksów lub pełnego tekstu zamiast LIKE ‚%wort%‘. Mierzę każdą zmianę indeksu przed i po uruchomieniu na żywo z tymi samymi profilami obciążenia.
Wzrost Używam kardynalności i histogramów do sprawdzania zestawów danych, aby nie indeksować rzadkich wartości. Utrzymuję liczbę indeksów na niskim poziomie, aby utrzymać obciążenie zapisu i wymagania dotyczące pamięci pod kontrolą. Skonsolidowane indeksy złożone zastępują kilka indeksów indywidualnych. Reguluję zadania podobne do autovacuum w MySQL, analizując je regularnie i odbudowując tylko wtedy, gdy jest to konieczne. Dzięki temu optymalizator jest niezawodny.
Ustawienia serwera, buforowanie i pamięć
InnoDB Rozmiar puli buforów określam na podstawie aktywnych rekordów danych i rozmiarów indeksów, a nie na podstawie wartości ogólnych. Zwiększam go do momentu, gdy rozmiar zestawu roboczego jest w dużej mierze w pamięci, a wskaźnik braku strony spada. Ustawiam tmp_table_size i max_heap_table_size, aby mniej tabel tymczasowych trafiało na dysk. Aby zapewnić bezpieczeństwo zapisu i opóźnienia, odpowiednio równoważę innodb_flush_log_at_trx_commit dla aplikacji. Na poziomie aplikacji buforuję częste wyniki i korzystam z buforowania HTTP, aby baza danych widziała mniej żądań.
Sprzęt a efekty sieciowe są uwzględniane w diagnozie: Wolne I/O pamięci masowej lub przeciążony procesor są natychmiast rozpoznawane przez zapytania. Dlatego mierzę IO-wait równolegle z metrykami bazy danych. Jeśli potrzebujesz więcej rezerw, zaplanuj skalowanie pionowe lub poziome z mierzalnym celem. Niniejszy przewodnik zawiera zwięzły przegląd wąskich gardeł, strojenia i zasobów: Sprzęt i pamięć podręczna. W ten sposób upewniam się, że nie przekręcam na ślepo niewłaściwego pokrętła.
Współbieżność i blokowanie w hostingu
Lock_time rośnie, gdy długie transakcje dotykają wielu wierszy lub gdy zadania czyszczenia działają w najlepszym czasie. Skracam operacje zapisu, dzielę duże aktualizacje na mniejsze partie, a tym samym skracam czas utrzymywania blokad. Odpowiednie poziomy izolacji zmniejszają konflikty bez narażania spójności danych. Odciążam hotspoty za pomocą drugorzędnych indeksów i odpowiednich warunków WHERE, dzięki czemu dotyczy to mniejszej liczby wierszy. Planuję zadania w tle w oknach czasowych o niskim natężeniu ruchu, aby działania użytkowników były traktowane priorytetowo.
Impasy Analizuję je przy użyciu powtarzających się wzorców: te same tabele, zmieniająca się kolejność, identyczne wiersze. Standaryzuję sekwencję dostępu w kodzie i procedurach składowanych. Logika ponawiania z jitterem rozwiązuje tymczasowe kolizje. Tam, gdzie to możliwe, izoluję najdroższe operacje w kolejkach zadań. To zauważalnie zmniejsza wariancję i zwiększa postrzeganą wydajność.
Zautomatyzowane alarmy i przepływy pracy
Rutyna bije akcjonizm: analizuję dziennik codziennie lub co tydzień, w zależności od ruchu i częstotliwości wydawania. Mały skrypt zlicza nowe wejścia w ciągu ostatnich kilku minut i wysyła mi wiadomość e-mail, jeśli wartość progowa wzrośnie. Generuję również regularne raporty pt-query-digest i zawsze mam oko na top 10. Dokładniej monitoruję dni premiery. Pozwala mi to rozpoznać regresje, zanim zauważą je użytkownicy.
#!/bin/bash
LOG_FILE="/var/log/mysql/slow-query.log"
THRESHOLD=100
RECENT_COUNT=$(awk -v cutoff="$(date -d '5 minut temu' '+%Y-%m-%dT%H:%M')" '/^# Time:/ { if ($3 >= cutoff) count++ } END { print count+0 }' "$LOG_FILE")
if [ "$RECENT_COUNT" -gt "$THRESHOLD" ]; then
echo "ALERT: $RECENT_COUNT slow queries" | mail -s "MySQL Alert" [email protected]
fi
Przejrzystość Tworzę jasny zakres odpowiedzialności: Kto reaguje na szczyty, kto dostosowuje indeksy, kto testuje wydania. Podsumowuję wyniki w krótkich dziennikach zmian. W ten sposób każdy członek zespołu rozumie, dlaczego dana zmiana została wprowadzona i jaki miała wpływ. Ustrukturyzowany proces oszczędza czas i zapobiega fałszywym alarmom.
Obrazy błędów i szybkie korekty
Pełna Skanowanie tabel powoduje nieproporcjonalnie wysokie obciążenie. Najpierw sprawdzam, czy w kolumnie filtru brakuje odpowiedniego indeksu lub czy wyrażenie blokuje indeks. Eliminuję wysoki lock_time skracając transakcje i wyrównując konkurencyjne operacje. Rozwijam przepełnione dzienniki za pomocą log_throttle_queries_not_using_indexes i realistycznego long_query_time. Natychmiast mierzę każdą poprawkę w stosunku do oryginalnych danych, aby sukcesy pozostały widoczne.
Przechowywanie-Rozpoznaję wąskie gardła poprzez zwiększanie oczekiwania IO i duże opóźnienia dysku podczas szczytów zapytań. Następnie redukuję niepotrzebne operacje zapisu, na przykład poprzez rzadsze aktualizowanie niezmiennych pól. Gdy tabele rosną, planuję strategie archiwizacji lub partycjonowania, aby gorące dane pozostały w pamięci. W przypadku instrukcji administratora w godzinach szczytu włączam log_slow_admin_statements, aby zidentyfikować ciche czynniki generujące koszty. Małe, ukierunkowane poprawki opłacają się tutaj szybciej niż duże reorganizacje.
Funkcje specjalne w środowiskach zarządzanych i chmurowych
zarządzany hosting lub usługi w chmurze często ograniczają dostęp do plików. W takich przypadkach ustawiam log_output na TABLE i oceniam powolny dziennik bezpośrednio z bazy danych. W MySQL 8.0 używam również SET PERSIST, aby trwale ustawić ustawienia bez bezpośredniego dostępu do my.cnf. W grupach parametrów chmury (np. dla usług zarządzanych) wprowadzam te same zmienne i planuję okno konserwacji dla restartu.
-- Jeśli dozwolone: trwałe ustawienia bez restartu
SET PERSIST slow_query_log = ON;
SET PERSIST long_query_time = 0.5;
SET PERSIST log_output = 'TABLE'; -- Alternatywa dla FILE dla ograniczonego dostępu do plików
-- Ocena z log_output=TABLE
SELECT start_time, user_host, query_time, lock_time, rows_sent, rows_examined, sql_text
FROM mysql.slow_log
ORDER BY query_time DESC
LIMIT 50;
WskazówkaPrzy dużym natężeniu ruchu, log_output=FILE może być bardziej wydajny, ponieważ logowanie tabelaryczne generuje dodatkowy narzut. Jednak w restrykcyjnych środowiskach TABLE jest często jedynym rozwiązaniem. Następnie ustawiam ściślejsze limity (np. min_examined_row_limit), aby utrzymać wolumen pod kontrolą.
Rotacja, przechowywanie i ochrona danych
Rotacja zapobiega zapełnianiu dysku przez logi. Rotuję codziennie lub według rozmiaru, kompresuję stare pliki i utrzymuję jasną politykę retencji (np. 14 dni). Po rotacji uruchamiam płukanie dziennika, aby MySQL zapisywał czysto do nowego pliku. Dzięki temu analiza i działanie są stabilne.
# /etc/logrotate.d/mysql-slow
/var/log/mysql/slow-query.log {
codziennie
rotacja 14
rozmiar 100M
kompresja
missingok
notifempty
create 640 mysql adm
postrotate
test -x /usr/bin/mysqladmin || exit 0
/usr/bin/mysqladmin flush-logs
endscript
}
Ochrona danych jest obowiązkowe: wolne logi mogą zawierać wartości parametrów. Ściśle ograniczam dostęp (uprawnienia do plików, grupy) i sprawdzam, czy logowane są wrażliwe dane. W razie potrzeby pracuję z wiązaniem parametrów w aplikacji, aby w dzienniku nie pojawiał się spersonalizowany zwykły tekst. W przypadku udostępniania zespołowego wolę udostępniać zagregowane raporty niż surowe dzienniki.
Użyj schematu wydajności i schematu systemu
System wydajności dostarcza metryki nawet bez aktywowanego slow logu. Aktywuję odpowiednich konsumentów dla zestawień, a następnie analizuję widoki systemu. Zaleta: mogę zobaczyć najlepsze trawienia i rozkład opóźnień niemal w czasie rzeczywistym, pogrupowane w podobne zapytania.
-- Aktywacja konsumenta dla historii wyciągów (o ile to możliwe w czasie wykonywania)
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME IN ('events_statements_history', 'events_statements_history_long');
-- Szybki przegląd drogich grup zapytań
SELECT schema_name, digest_text, count_star,
ROUND(sum_timer_wait/1e12, 3) AS total_s,
ROUND(avg_timer_wait/1e9, 3) AS avg_ms,
ROUND(max_timer_wait/1e9, 3) AS pmax_ms
FROM sys.statement_analysis
ORDER BY sum_timer_wait DESC
LIMIT 10;
Połączenie z powolnego dziennika (powolne wartości odstające) i schematu wydajności (szerokość, częstotliwość) pokazuje mi zarówno pojedyncze przypadki, jak i systematyczne czynniki kosztotwórcze. Porównuję oba widoki z wzorcami ruchu, aby utworzyć priorytetowe zadania do wykonania.
EXPLAIN ANALYZE i Optimiser Trace
WYJAŚNIJ ANALIZĘ (od MySQL 8.0.18) uzupełnia szacunki o zmierzone czasy. Porównuję szacunki wierszy z rzeczywistymi wartościami i odkrywam błędne oceny optymalizatora. W przypadku sprzecznych planów analizuję ślad optymalizatora, aby sprawdzić, dlaczego indeks nie został wybrany.
-- Plan z wartościami zmierzonymi
WYJAŚNIJ ANALIZĘ
SELECT o.id, o.created_at
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE c.country = 'DE' AND o.status = 'paid'
ORDER BY o.created_at DESC
LIMIT 50;
-- Śledzenie decyzji optymalizatora
SET optimizer_trace="enabled=on";
SELECT ...; -- zapytanie do przeanalizowania
SELECT TRACE FROM information_schema.OPTIMIZER_TRACE\G
SET optimizer_trace="enabled=off";
WynikJeśli szacunki są znacznie rozbieżne, aktualizuję statystyki (ANALYZE TABLE), dodaję histogramy lub przekształcam indeksy / zapytania, aby selektywność zaczęła działać wcześnie.
Przepisz wzorce, które prawie zawsze działają
LUB do UNION ALLWiele warunków OR na różnych kolumnach często uniemożliwia wykorzystanie indeksu. Rozdzielam je na dwa selektywne zapytania i łączę wyniki, jeśli można wykluczyć duplikaty.
-- Przed:
SELECT * FROM t WHERE a = ? OR b = ?;
-- Lepiej:
(SELECT * FROM t WHERE a = ?)
UNION ALL
(SELECT * FROM t WHERE b = ? AND a ?);
PaginacjaOFFSET/LIMIT staje się kosztowny wraz ze wzrostem OFFSET. Przełączam się na paginację zestawów klawiszy i używam odpowiedniego klucza sortowania (najlepiej indeksowanego i monotonicznego).
-- Drogie:
SELECT id, title FROM posts ORDER BY created_at DESC LIMIT 50 OFFSET 5000;
-- Lepiej (zestaw kluczy):
SELECT id, title
FROM posts
WHERE created_at < :cursor
ORDER BY created_at DESC
LIMIT 50;
Wskaźniki złożoneKolejność się liczy. Sortuję kolumny w indeksie zgodnie z selektywnością i wzorcem zapytania (najpierw filtr WHERE, a następnie sortowanie kolumn). Celem jest indeks pokrywający, który pozwala uniknąć sortowania plików i wyszukiwania tabel.
Funkcjonalne i generowane indeksy w MySQL 8
Wyrażenia w WHERE/JOIN często blokują indeksy. W MySQL 8.0 specjalnie indeksuję wyrażenia lub pracuję z wygenerowanymi kolumnami, aby utworzyć sargability. Jest to szczególnie przydatne w przypadku CAST dla metawartości numerycznych lub pól JSON.
-- Przykład: sortowanie numeryczne w polu tekstowym
ALTER TABLE product ADD COLUMN price_num DECIMAL(10,2)
GENERATED ALWAYS AS (CAST(price AS DECIMAL(10,2))) STORED;
CREATE INDEX idx_product_price_num ON product(price_num);
-- Zapytanie bez CAST i z indeksem
SELECT * FROM product
WHERE price_num BETWEEN 10 AND 50
ORDER BY price_num;
PraktykaTestuję, czy nowy indeks naprawdę działa (EXPLAIN) i mierzę efekt w powolnym dzienniku. Wygenerowane kolumny pomagają również skutecznie filtrować prefiksy lub znormalizowane warianty (LOWER(email)).
Bardziej ukierunkowane podejście do wzorców CMS/sklepu
Meta tabele (np. wp_postmeta) korzystają z połączonych indeksów na (post_id, meta_key) lub (meta_key, meta_value). W przypadku częstych filtrów na meta_value_numeric używam wygenerowanych kolumn, jak powyżej, zamiast CASTowania w każdym zapytaniu. Przyspieszam strony wyszukiwania, odrzucając redundancje (światło denormalizacji) i czyniąc dostęp do odczytu przyjaznym dla indeksu.
-- Typowe dla WordPress: szybki dostęp do metadanych postu
CREATE INDEX idx_postmeta_postid_metakey ON wp_postmeta(post_id, meta_key);
CREATE INDEX idx_postmeta_metakey_metavalue ON wp_postmeta(meta_key, meta_value(100));
Kasa-Optymalizuję ścieżki pod kątem minimalnych czasów blokowania: krótkie transakcje, tylko niezbędne wiersze i indeksy dokładnie dla używanych warunków WHERE. W przypadku raportów planuję asynchroniczną agregację (tabele pośrednie), aby nie spowalniać przepływu użytkowników.
Limity powolnego dziennika i dodatkowe metryki
Wiele małych, szybkich zapytań nie są zauważalne w powolnym dzienniku, ale zwiększają obciążenie. Dlatego też śledzę również przepustowość (zapytania/s), 95/99 percentyl i odsetek zapytań bez indeksu. W narzędziach Performance Schema lub APM rozpoznaję wzorce N+1, które następnie rozwiązuję za pomocą złączeń, procesów ładowania wsadowego lub buforowania.
Pobieranie próbek jest przydatna, gdy dzienniki stają się zbyt duże. Zwiększam nieznacznie long_query_time lub ustawiam min_examined_row_limit, aby uwzględnić tylko odpowiednie zapytania. Ważne: Zawsze należy odnotowywać zmiany, aby szeregi czasowe pozostały porównywalne.
Metoda pracy: Od ustaleń do trwałej poprawy
Linia bazowa Po pierwsze: zapisuję raport wstępny (okno czasowe, ruch, konfiguracja). Następnie optymalizuję jedną rodzinę zapytań po drugiej i porównuję identyczne okna czasowe. Każda poprawka jest dokumentowana w repozytorium (co? dlaczego? zmierzona wartość przed/po?). W ten sposób sukcesy pozostają identyfikowalne i odporne na regresję.
# Szorstka procedura (przykład)
1) pt-query-digest --since '7d' slow-query.log > baseline.txt
2) Wybierz 3 najlepsze skróty zapytań (według całkowitego czasu)
3) EXPLAIN/EXPLAIN ANALYZE, opracowanie indeksu i propozycji przepisania
4) Wygenerowanie danych testowych, symulacja profilu obciążenia
5) Wdrożenie z monitorowaniem (ściślejsze limity przez 48 godzin)
6) Raport porównawczy: pt-query-digest --since '48h' > after.txt
7) Dokumentowanie wyników, planowanie następnej części
Stabilność planu Monitoruję optymalizator w czasie: jeśli plany się zmieniają (nowe wersje, zmienione statystyki), sprawdzam histogramy, ANALYZE TABLE i krajobraz indeksów. Podpowiedzi ustawiam tylko selektywnie i w udokumentowany sposób, aby nie wiązać optymalizatora na stałe.
Podsumowanie w jasnych krokach
Start Oznacza to: aktywowanie dziennika, ustawienie rozsądnych wartości granicznych, zebranie pierwszego tygodnia danych. Następnie podsumowuję za pomocą pt-query-digest, priorytetyzuję według całkowitego czasu i wariancji i wybieram najlepsze sterowniki. Optymalizuję zapytania za pomocą EXPLAIN, warunków sargable i odpowiednich indeksów oraz kontroluję blokowanie za pomocą krótszych transakcji. Po stronie serwera odpowiednio ustawiam bufory, tabele tymczasowe i strategie spłukiwania. Na koniec automatyzuję alarmy i regularnie powtarzam cykl - dzięki temu baza danych działa szybko, nawet gdy rośnie ruch i ilość danych.


