...

Wykorzystanie schematu wydajności MySQL w praktyce w celu poprawy wydajności

Dla lepszego Wydajność MySQL Korzystam ze schematu wydajności, aby bezpośrednio za pomocą SQL analizować dane dotyczące czasu wykonania, operacji oczekiwania, blokad, pamięci i operacji wejścia/wyjścia. Dzięki temu szybciej identyfikuję przyczyny spowolnienia instrukcji i podejmuję ukierunkowane działania w celu Strojenie oraz monitorowanie na podstawie [2][3][15].

Punkty centralne

Poniższe wskazówki pomagają mi skutecznie korzystać ze schematu wydajności.

  • Aktywacja oraz zoptymalizowana konfiguracja z odpowiednimi przyrządami i odbiornikami
  • Skróty oświadczeń wykorzystać do wykrywania kosztownych wzorów i punktów newralgicznych
  • Zdarzenia oczekiwania, wspólna analiza blokad i operacji wejścia/wyjścia w celu zidentyfikowania rzeczywistych wąskich gardeł
  • Schemat systemu jako skrót oznaczający szybki i praktyczny wgląd w sytuację
  • Iteracyjny Schemat postępowania: pomiar, izolacja, zmiana, ponowny pomiar

Włączenie i odpowiednia konfiguracja schematu wydajności

Najpierw sprawdzam, czy schemat_wydajności jest włączona, ponieważ najnowsze wersje MySQL zazwyczaj mają tę opcję domyślnie włączoną [1][12]. Jeśli jej brakuje, ustawiam w pliku [mysqld]-blok my.cnf zmienna performance_schema=ON i uruchom ponownie serwer. Następnie skonfiguruję konkretne urządzenia i odbiorniki, zamiast na stałe ustawiać wszystko na maksymalną moc. Skupiam się na oświadczenie/%, wait/% oraz odpowiednie ścieżki wejścia/wyjścia, aby zebrać miarodajne dane bez zbędnego obciążenia [6]. Przed rozpoczęciem nowej serii pomiarów czyszczę odpowiednie tabele historii i zaczynam od czystej Podstawa.

Szybkie sukcesy dzięki schematowi Sys

Aby szybko zorientować się w sytuacji, często sięgam po sys-Schema, ponieważ w sensowny sposób zagregowuje surowe dane z Performance Schema [13]. Dzięki temu w ciągu kilku minut znajduję zapytania, które mają największy udział w czasie wykonania. Zaczynam od najczęściej wykonywanych instrukcji, sprawdzam widoki operacji wejścia/wyjścia plików i przeglądam podsumowania oczekiwań dla wątków. Gdy tylko zidentyfikuję punkt newralgiczny, wracam do tabel surowych i doprecyzowuję analizę. Kto przeanalizuje plany zapytań, może przy pomocy odpowiednich Wskazówki dotyczące Optimizera często odczuwalne już po krótkim czasie Wygrane osiągnąć.

Wybór odpowiednich narzędzi i odbiorników

Zaczynam szeroko, ale staram się, by obserwacja była kontrolowana: najpierw uruchamiam najważniejsze Instrumenty dla instrukcji SELECT, WAIT i operacji wejścia/wyjścia, a potem wyłączam wszystko, co nie dostarcza żadnych danych [6]. Elementy przetwarzające dane, takie jak historia zdarzeń i tabele podsumowujące, muszą wspierać pytania, na które chcę uzyskać odpowiedzi. Jeśli chodzi na przykład o szczyty opóźnień, sprawdzam w podsumowanie_oczekiwań_na_wydarzenia_globalne_według_nazwy_wydarzenia i porównaj to z podsumowanie_oświadczeń_dotyczących_wydarzeń_według_podsumowania. Jeśli pojawiają się opóźnienia we/wy, sprawdzam podsumowanie plików według nazwy zdarzenia oraz podsumowanie_czasów_oczekiwania_na_operacje_we/wy_według_tabeli. Takie celowe doboru pozwala ograniczyć obciążenie systemowe, a mimo to zapewnia solidne Dane.

Podsumowania oświadczeń: rozpoznawanie wzorców, zmniejszanie obciążenia

Dzięki skrótom wyciązków widzę, które wzorce są stale kosztowne, nawet jeśli poszczególne zapytania zawierają różne literały [17]. Sortuję wyniki według całkowitego czasu, liczby wykonań i średniego opóźnienia, aby ustalić priorytety. W tym celu korzystam dodatkowo z Analiza dziennika powolnych zapytań wstecz, aby nie przeoczyć rzadkich wartości odstających. Jeśli podsumowania wskazują wartości szczytowe, sprawdzam indeksy, strategie JOIN i kolejność filtrów za pomocą WYJAŚNIENIE. Następnie potwierdzam skuteczność tych działań, przeprowadzając kolejne pomiary w schemacie wydajności, aby optymalizacje pozostały mierzalne.

Analiza zdarzeń oczekiwania, blokad i operacji wejścia/wyjścia

Gdy zapytania utkną, sprawdzam tabele „Wait” i „Lock”, aby ustalić rzeczywistą Przyczyna można znaleźć [3]. Jeśli wiele wątków korzysta z tych samych tabel, oznacza to, że table_lock-Czekam na pojawienie się konkurencji. Jeśli zdarzenia związane z operacjami wejścia/wyjścia plików wykazują duże opóźnienia, sprawdzam pamięć masową i buforowanie, a także wzorce zapytań za pomocą rozległych skanów. Jeśli zauważę blokady wierszy InnoDB, analizuję najczęściej używane rekordy, czas trwania transakcji oraz pokrycie indeksów. Dopiero gdy wszystkie elementy układanki do siebie pasują, zajmuję się parametrami serwera, schematem lub kodem.

Monitorowanie pamięci: pamięć i pula buforów

Problemy z pamięcią rozwiązuję, analizując wykorzystanie tabel pamięciowych i buforów InnoDB. Jeśli zapotrzebowanie na pamięć poszczególnych komponentów wzrasta, dostosowuję limity i sprawdzam, czy pamięci podręczne nie przechowują nieprawidłowych danych. Jeśli pamięć podręczna InnoDB jest niewystarczająca, zwiększam jej udział lub poprawiam lokalność zapytań. Osoby, które chcą zagłębić się w ten temat, mogą skorzystać z Optymalizacja puli buforów osiągnąć znaczny spadek opóźnień. Potwierdzam ten efekt za pomocą Podsumowanie-tabele i sprawdzaj, czy wskaźniki trafień LRU oraz czasy oczekiwania na operacje wejścia/wyjścia zmierzają w dobrym kierunku.

Iteracyjny proces diagnostyczny na co dzień

Zawsze pracuję w jasno określonych cyklach, aby nie tracić czasu, a zmiany pozostawały mierzalne [3]. Najpierw odtwarzam problem przy kontrolowanym obciążeniu. Następnie gromadzę wyniki pomiarów w kilku, ukierunkowanych tabelach i wyodrębniam najbardziej podejrzane elementy. Następnie wprowadzam zmiany w tych elementach, które obiecują największe korzyści: indeks, zapytanie, parametry lub kod. Na koniec ponownie dokonuję pomiarów i dokumentuję krótkie Przed/po-tabele, dzięki którym zespół od razu dostrzeże efekty.

Przykłady zapytań: Od surowych danych do decyzji

W odniesieniu do typowych pytań sporządziłem zwięzłe fragmenty kodu SQL, z których korzystam na co dzień. Tabela przedstawia przykłady, z których często korzystam, oraz ich przeznaczenie. Dostosowuję filtry, takie jak LIMIT lub ORDER BY w zależności od konkretnego przypadku. Najważniejsze jest to, by najpierw sformułować hipotezę, a dopiero potem przeprowadzić ukierunkowaną analizę i podjąć jasną decyzję. W ten sposób zapewniam, że analiza jest ukierunkowana i unikam zbędnych Obciążenie.

Tabela(y) schematów wydajnościowych Cel Ważne kolumny Przykładowe zapytanie
podsumowanie_oświadczeń_dotyczących_wydarzeń_według_podsumowania Znajdź drogie wzory digest_text, count_star, sum_timer_wait SELECT digest_text, count_star, sum_timer_wait/1e12 AS sec_total FROM performance_schema.events_statements_summary_by_digest ORDER BY sec_total DESC LIMIT 10;
podsumowanie_oczekiwań_na_wydarzenia_globalne_według_nazwy_wydarzenia Punkty o dużym natężeniu oczekiwania nazwa_wydarzenia, sum_timer_wait SELECT event_name, sum_timer_wait/1e12 AS sec_total FROM performance_schema.events_waits_summary_global_by_event_name ORDER BY sec_total DESC LIMIT 10;
podsumowanie_czasów_oczekiwania_na_operacje_we/wy_według_tabeli Sprawdź operacje wejścia/wyjścia tabeli schemat_obiektu, nazwa_obiektu, read_timer_wait SELECT object_schema, object_name, (read_timer_wait+write_timer_wait)/1e12 AS sec_total FROM performance_schema.table_io_waits_summary_by_table ORDER BY sec_total DESC LIMIT 10;
podsumowanie_pamięci_globalne_według_nazwy_zdarzenia Znajdź programy zajmujące dużo pamięci nazwa_wydarzenia, current_alloc SELECT event_name, current_alloc/1024/1024 AS mb FROM performance_schema.memory_summary_global_by_event_name ORDER BY mb DESC LIMIT 10;

Zakład produkcyjny: minimalizacja kosztów ogólnych, maksymalizacja efektywności

Podczas pracy na żywo nie włączam instrumentów na ślepo, lecz wybieram tylko te, które odpowiadają na moje pytanie [6]. Zdarzenia o wysokiej częstotliwości traktuję ostrożnie i ograniczam długość okien historii. W przypadku dłuższych obserwacji preferuję skompresowane podsumowania i zapisuję migawki na nośnikach zewnętrznych. Zwracam uwagę na wpis w konfiguracja_schematu_wydajności_odbiorców, abym mógł kierować zbiorami, zamiast pozwalać im działać samodzielnie. Takie podejście pozwala na analizę skuteczny i chroni serwer.

Precyzyjna regulacja: instrumenty i urządzenia konsumenckie do konfiguracji w praktyce

Aby szybko uzyskać wiarygodne wyniki, celowo konfiguruję przyrządy i odbiorniki. Szczególnie ważne są oświadczenie/%, wait/%, wait/io/% oraz – w razie potrzeby – wybrane pamięć/%-ścieżki. Najpierw aktywuję tylko to, co niezbędne, a następnie rozszerzam zakres, jeśli nadal pozostają konkretne pytania bez odpowiedzi. Liczniki czasu w schemacie wydajności mierzą w pikosekundach; aby uzyskać wartości w sekundach, dzielę kolumny opóźnień przez 1e12.

Typowy punkt początkowy w czasie wykonywania:

-- Włącz kluczowe instrumenty
UPDATE performance_schema.setup_instruments
  SET ENABLED='YES', TIMED='YES'
  WHERE NAME LIKE 'statement/%'
 OR NAME LIKE 'wait/io/%'
 OR NAME LIKE 'wait/lock/%';

-- Wybierz kluczowe moduły odbiorcze
UPDATE performance_schema.setup_consumers
  SET ENABLED='YES'
  WHERE NAME IN ('global_instrumentation',
 'thread_instrumentation',
 'statements_digest',
 'events_statements_current',
                 'events_statements_history',
 'events_waits_current',
 'events_waits_history');

-- Wyczyść podsumowania, aby uzyskać nową serię pomiarów
TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
TRUNCATE TABLE performance_schema.events_waits_summary_global_by_event_name;
TRUNCATE TABLE performance_schema.table_io_waits_summary_by_table;

Jeśli potrzebuję analiz pamięci, włączam je wybiórczo pamięć/%-narzędzia. Wiąże się to z większymi kosztami ogólnymi, ale opłaca się w przypadku wycieków lub dużego obciążenia alokatora.

Wymiary: zrozumienie pojęć „użytkownik”, „host” i „schemat”

Szczyty mocy często nie mają charakteru ogólnego, lecz dotyczą określonych Użytkownik, Gospodarze lub Schemat ograniczone. Schemat wydajności dostarcza w tym celu zestawienia dla każdego konta i hosta. Dodatkowo w zestawieniu zawarta jest kolumna nazwa_schematu, aby zawęzić listę hotspotów dla każdej bazy danych.

Przykłady, z których często korzystam:

  • Najpopularniejsze schematy według całkowitego czasu trwania: SELECT schema_name, SUM(sum_timer_wait)/1e12 AS sec_total FROM performance_schema.events_statements_summary_by_digest GROUP BY schema_name ORDER BY sec_total DESC LIMIT 10;
  • Użytkownicy/serwery powodujące największe opóźnienia (według kont): SELECT user, host, SUM(sum_timer_wait)/1e12 AS sec_total FROM performance_schema.events_statements_summary_by_account_by_event_name GROUP BY user, host ORDER BY sec_total DESC LIMIT 10;
  • Wątki o najdłuższym czasie oczekiwania: SELECT thread_id, SUM(sum_timer_wait)/1e12 AS sec_total FROM performance_schema.events_waits_summary_by_thread_by_event_name GROUP BY thread_id ORDER BY sec_total DESC LIMIT 10;

Dzięki tym widokom mogę precyzyjnie rozdzielać segmenty ruchu i stosować ograniczenia przepustowości, buforowanie lub wdrażać warianty zapytań dla poszczególnych klientów.

Wyświetlanie długotrwałych transakcji i blokad metadanych

Transakcje trwające zbyt długo lub nieaktywne blokują punkty kontrolne, operacje czyszczenia (Purge) oraz konkurencyjne operacje DML. Dlatego regularnie sprawdzam widok transakcji oraz czasy oczekiwania MDL:

  • Aktywne transakcje: SELECT thread_id, timer_wait/1e12 AS sec_running, state FROM performance_schema.events_transactions_current ORDER BY sec_running DESC LIMIT 10;
  • Wykrywanie blokad metadanych (konkurencja DDL/DML): SELECT event_name, SUM(sum_timer_wait)/1e12 AS sec_total FROM performance_schema.events_waits_summary_global_by_event_name WHERE event_name LIKE 'wait/lock/metadata/sql/mdl%' GROUP BY event_name ORDER BY sec_total DESC;

Jeśli dominuje MDL, przeprojektowuję okna DDL, minimalizuję czas utrzymywania blokad w kodzie (krótsze transakcje) i sprawdzam, czy zbędne AUTOCOMMIT=0-Nie należy pozostawiać sesji otwartych niepotrzebnie długo.

Replikacja, kopie zapasowe i skutki uboczne w zasięgu wzroku

Procesy replikacji i tworzenia kopii zapasowych pojawiają się w widokach oczekiwań i operacji wejścia/wyjścia. Opóźnienia można zawęzić, analizując statusy procesów roboczych i oczekiwania na pliki. Sprawdzam procesy robocze aplikacji, wątki SQL oraz zdarzenia związane z operacjami wejścia/wyjścia plików:

  • Pracownicy aplikacji o dużym opóźnieniu: SELECT worker_id, THREAD_ID, APPLYING_TRANSACTION, APPLYING_STATE FROM performance_schema.replication_applier_status_by_worker;
  • Miejsca o największym obciążeniu operacji wejścia/wyjścia plików podczas tworzenia kopii zapasowych: SELECT event_name, (sum_timer_read+sum_timer_write)/1e12 AS sec_total FROM performance_schema.file_summary_by_event_name ORDER BY sec_total DESC LIMIT 10;

Jeśli dostrzegam tutaj wąskie gardła, oddzielam fazy wejścia/wyjścia (np. okienkowanie, harmonogram wejścia/wyjścia, ograniczanie kopii zapasowych) lub zwiększam liczbę równoległych procesów aplikujących, o ile obciążenie jest skalowalne.

Okna czasowe, migawki i strategie resetowania

Pomiary wymagają jasno określonych przedziałów czasowych. Aby uzyskać porównanie „przed/po“, stosuję celowe resetowanie i migawki:

  • Zresetuj podsumowania, aby uzyskać nowe przedziały czasowe: TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
  • Utwórz kopię zapasową migawki na nośniku zewnętrznym: CREATE TABLE IF NOT EXISTS perf_snapshot_digest AS SELECT NOW() AS captured_at, * FROM performance_schema.events_statements_summary_by_digest;
  • Przechowywać krótkie okna historyczne (segment konsumencki), a długoterminowe trendy gromadzić zewnętrznie.

W ten sposób mogę w bezpieczny sposób porównywać i dokumentować optymalizacje niezależnie od wdrożeń, zmian parametrów czy modyfikacji schematów.

Zarządzanie obciążeniem i zapotrzebowaniem na pamięć

Częstym błędnym przekonaniem jest to, że schemat wydajnościowy jest „zbyt kosztowny“. W praktyce ograniczam obciążenie dzięki trzem działaniom: aktywuję tylko istotne instrumenty, utrzymuję krótką długość historii dla często odwiedzanych odbiorców danych historycznych oraz odpowiednio dobieram parametry pamięci. W przypadku dużej zmienności podsumowań celowo zwiększam rozmiar_podsumowań_schematu_wydajności a także – w razie potrzeby – performance_schema_max_sql_text_length, aby tożsamości pozostały stabilne. Jeśli potrzebne są narzędzia typu „memory”, ograniczam ich stosowanie do problematycznych podsystemów.

Typowe elementy regulacyjne w my.cnf:

[mysqld]
performance_schema=ON
performance-schema-instrument='statement/%=ON'
performance-schema-instrument='wait/io/%=ON'
performance-schema-instrument='wait/lock/%=ON'
performance-schema-consumer-events-statements-history=ON
performance-schema-consumer-events-waits-history=ON
# Opcjonalnie, jeśli występuje wiele wzorców:
performance_schema_digests_size=10000
performance_schema_max_sql_text_length=4096

Przy każdej zmianie sprawdzam, czy obciążenie procesora, opóźnienia i wykorzystanie pamięci pozostają na stałym poziomie. Gdy tylko diagnostyka zostanie zakończona, przywracam konfigurację do „minimalnego poziomu operacyjnego“.

Typowe problemy i szybkie rozwiązania

  • Duża kwota w podsumowanie_oświadczeń_dotyczących_wydarzeń_według_podsumowania, wiele skanów: Sprawdź indeksy, kolejność filtrów i możliwość sargowania; potwierdź za pomocą WYJAŚNIENIE i powtórzyć pomiar (czas trawienia musi wyraźnie się skrócić).
  • Dominanta table_io_waits w kilku tabelach: Poprawa lokalizacji operacji wejścia/wyjścia (dostępy do indeksów klastrowych, indeksy pokrywające), zmniejszenie ilości danych na instrukcję, w razie potrzeby stosowanie przetwarzania partiami zamiast operacji na całej tabeli.
  • Czas oczekiwania na wait/lock/innodb/%: Identyfikowanie „hot records”, łagodzenie konfliktów zapisu poprzez mniejsze transakcje, odpowiednie indeksy lub kolejkowanie.
  • Wiele wait/lock/metadata/sql/mdl: Zaplanuj okna DDL, ONLINE- preferować operacje zgodne z tym mechanizmem, oddzielić czytniki od zapisów poprzez krótsze transakcje.
  • Wzrost zapasów w podsumowanie_pamięci_globalne_według_nazwy_zdarzenia: Dokładniejsze ustawienie limitów, celowe ograniczenie pamięci podręcznej zapytań, identyfikacja problematycznych komponentów za pomocą pamięć/% przedstawić szczegółowy podział.
  • „Spiky“ opóźnienie przy skądinąd niebudzących zastrzeżeń wartościach średnich: Wykorzystaj widoki systemowe z percentylami i w razie potrzeby mierz szczyty obciążenia osobno (węższe okno, krótka historia, ukierunkowane narzędzia).

Korelacja: od wątku do instrukcji i oczekiwania

Aby szybko ustalić powiązania między przyczynami, łączę performance_schema.threads z tabelami „Current” i „History” dotyczącymi instrukcji i oczekiwań. Dzięki temu widzę, co dany wątek robił ostatnio i na co czeka. Krótki opis przebiegu:

  1. Osoby dotknięte tą sytuacją PROCESSLIST_ID Odpowiednio THREAD_ID z performance_schema.threads przyniesć.
  2. Ostatnie oświadczenie opublikowane za pośrednictwem historia_wydarzeń_oświadczeń ustalić (zgodnie z THREAD_ID oraz sortowanie według czasu).
  3. Równoległe oczekiwania z historia_oczekiwań_na_wydarzenia sprawdzić, aby zobaczyć przyczyny blokady lub oczekiwania na operacje wejścia/wyjścia.

Ten wzorzec „Drilldown & Join“ jest moim standardowym rozwiązaniem, gdy poszczególne sesje lub żądania internetowe zaczynają działać nieprawidłowo.

Etapy kontroli jakości i ciągłe doskonalenie wyników

Aby optymalizacje nie poszły na marne, wprowadzam proste „bramki jakości” (Quality Gates): przed i po każdym wydaniu uruchamiane są zdefiniowane zapytania z Performance Schema. Tworzę kopie zapasowe, porównuję wskaźniki (Top-Digests, Top-Waits, operacje we/wy na tabelę) i dokumentuję odchylenia. W procesie CI/CD dodaję reprezentatywne profile obciążenia oraz wartości graniczne dla 95. percentyla. Jeśli któryś z wskaźników wykracza poza te ramy, istnieje jasny kanał zwrotny: sprawdzenie hipotezy, skupienie się na odpowiednich narzędziach, wdrożenie poprawki, ponowny pomiar.

Unikanie źródeł błędów

  • Zbyt wiele instrumentów na dłuższą metę: Diagnoza ma charakter tymczasowy; w trybie normalnej pracy należy pozostawić aktywny jedynie zestaw minimalny.
  • Mieszane okresy pomiarowe: Przed nowymi testami należy wyczyścić podsumowania, w przeciwnym razie stare dane osłabią ich miarodajność.
  • Nieprawidłowa jednostka czasu: Czas jest podawany w pikosekundach; konsekwentnie przez 1e12 udział.
  • Lawina streszczeń: Zmienne literały mogą zakłócać wzorce; należy znormalizować kod SQL i performance_schema_max_sql_text_length sprawdzić.
  • Historia jest zbyt długa: Duża częstotliwość zdarzeń + długa historia powodują obciążenie; okno historii powinno być krótkie, migawki przechowywane zewnętrznie.

Lista kontrolna dla praktyki

  • Zdefiniować pytanie, sformułować hipotezę.
  • Wykorzystać odpowiednie narzędzia/konsumentów, ograniczając koszty ogólne do minimum.
  • Wyczyścić podsumowania, wybrać krótki przedział pomiarowy.
  • Sprawdzić Top-Digests, czasy oczekiwania i operacje wejścia/wyjścia; zweryfikować punkty newralgiczne.
  • Precyzyjne dostosowanie indeksu/zapytania/kodu/parametru.
  • Ponownie dokonać pomiaru, wykonać zrzuty ekranu, udokumentować decyzję.
  • Ograniczyć konfigurację do minimum operacyjnego.

Krótkie podsumowanie: moje podejście w praktyce

Aktywuję schemat wydajności w sposób ukierunkowany, zaczynam od szerokiego zakresu, a następnie zawężam go do najbardziej przydatnych elementów Instrumenty [1][2][12]. Aby uzyskać szybki przegląd, korzystam ze schematu Sys, a w razie potrzeby zagłębiam się w dane surowe [13]. Najpierw zajmuję się newralgicznymi punktami w podsumowaniach i zdarzeniach oczekiwania, zanim zacznę zmieniać parametry [3][15][17]. Następnie potwierdzam każdą zmianę nowymi pomiarami, aby postępy były widoczne i powtarzalne. W ten sposób zapewniam trwale niezawodne Czasy reakcji i oszczędzam sobie zbędnej pracy.

Artykuły bieżące