Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Ściągawka z wydajnością MySQL

MySQL jest obszerny i ma wiele obszarów do optymalizacji i dostosowania w celu uzyskania pożądanej wydajności. Niektóre zmiany mogą być wprowadzane dynamicznie, inne wymagają restartu serwera. Dość często można znaleźć instalację MySQL z domyślną konfiguracją, chociaż ta ostatnia może nie być odpowiednia z punktu widzenia obciążenia i konfiguracji.

Oto kluczowe obszary MySQL, które zaczerpnąłem z różnych źródeł eksperckich ze świata MySQL, a także z naszych własnych doświadczeń w firmie Manynines. Ten blog posłuży jako ściągawka do dostrojenia wydajności i ponownego uczynienia Twojego MySQL wspaniałym :-)

Przyjrzyjmy się tym, przedstawiając kluczowe obszary w MySQL.

Zmienne systemowe

MySQL ma wiele zmiennych, które możesz rozważyć. Niektóre zmienne są dynamiczne, co oznacza, że ​​można je ustawić za pomocą instrukcji SET. Inne wymagają ponownego uruchomienia serwera po ich ustawieniu w pliku konfiguracyjnym (np. /etc/my.cnf, etc/mysql/my.cnf). Jednak omówię typowe rzeczy, które są dość powszechne przy dostrajaniu, aby zoptymalizować serwer.

sort_buffer_size

Ta zmienna kontroluje, jak duży jest bufor sortowania plików, co oznacza, że ​​ilekroć zapytanie musi posortować wiersze, wartość tej zmiennej jest używana do ograniczenia rozmiaru, który musi zostać przydzielony. Zwróć uwagę, że ta zmienna jest przetwarzana na zapytanie (lub na połączenie), co oznacza, że ​​byłaby głodna pamięci, gdy ustawisz ją wyżej i jeśli masz wiele połączeń, które wymagają sortowania wierszy. Możesz jednak monitorować swoje potrzeby, sprawdzając globalną zmienną statusu Sort_merge_passes. Jeśli ta wartość jest duża, należy rozważyć zwiększenie wartości zmiennej systemowej sort_buffer_size. W przeciwnym razie przejdź do umiarkowanego limitu, którego potrzebujesz. Jeśli ustawisz to zbyt nisko lub jeśli masz duże zapytania do przetworzenia, efekt sortowania wierszy może być wolniejszy niż oczekiwano, ponieważ dane są pobierane losowo podczas nurkowań na dysku. Może to spowodować pogorszenie wydajności. Najlepiej jednak naprawić swoje zapytania. W przeciwnym razie, jeśli Twoja aplikacja jest zaprojektowana do ściągania dużych zapytań i wymaga sortowania, efektywne jest użycie narzędzi obsługujących buforowanie zapytań, takich jak Redis. Domyślnie w MySQL 8.0 bieżący zestaw wartości to 256 KiB. Ustaw to odpowiednio tylko wtedy, gdy masz zapytania, które intensywnie używają lub wywołują sortowanie.

read_buffer_size

Dokumentacja MySQL wspomina, że ​​dla każdego żądania, które wykonuje sekwencyjne skanowanie tabeli, przydziela bufor odczytu. Zmienna systemowa read_buffer_size określa rozmiar buforu. Jest to również przydatne dla MyISAM, ale ta zmienna wpływa również na wszystkie silniki pamięci masowej. W przypadku tabel MEMORY służy do określenia rozmiaru bloku pamięci.

Zasadniczo każdy wątek, który wykonuje sekwencyjne skanowanie tabeli MyISAM, alokuje bufor o tym rozmiarze (w bajtach) dla każdej skanowanej tabeli. Dotyczy to również wszystkich silników pamięci masowej (w tym InnoDB), więc jest pomocny w przypadku zapytań sortujących wiersze za pomocą ORDER BY i buforujących ich indeksy w pliku tymczasowym. Jeśli wykonujesz wiele skanowań sekwencyjnych, zbiorczo wstawiasz do tabel partycji, buforując wyniki zagnieżdżonych zapytań, a następnie rozważ zwiększenie jego wartości. Wartość tej zmiennej powinna być wielokrotnością 4 KB. Jeśli jest ustawiony na wartość, która nie jest wielokrotnością 4 KB, jego wartość zostanie zaokrąglona w dół do najbliższej wielokrotności 4 KB. Weź pod uwagę, że ustawienie wyższej wartości spowoduje zużycie dużej części pamięci twojego serwera. Proponuję nie używać tego bez odpowiedniego porównania i monitorowania środowiska.

read_rnd_buffer_size

Ta zmienna zajmuje się odczytywaniem wierszy z tabeli MyISAM w kolejności posortowanej po operacji sortowania kluczy, wiersze są odczytywane przez ten bufor, aby uniknąć przeszukiwania dysku. Dokumentacja mówi, że podczas odczytywania wierszy w dowolnej kolejności lub z tabeli MyISAM w kolejności posortowanej po operacji sortowania kluczy, wiersze są odczytywane przez ten bufor (i określane przez ten rozmiar bufora), aby uniknąć przeszukiwania dysku. Ustawienie zmiennej na dużą wartość może znacznie poprawić wydajność ORDER BY. Jest to jednak bufor przydzielany dla każdego klienta, więc nie należy ustawiać zmiennej globalnej na dużą wartość. Zamiast tego zmień zmienną sesji tylko z poziomu tych klientów, którzy muszą uruchamiać duże zapytania. Należy jednak wziąć pod uwagę, że nie dotyczy to MariaDB, szczególnie w przypadku korzystania z MRR. MariaDB używa mrr_buffer_size, podczas gdy MySQL używa read_buffer_size read_rnd_buffer_size.

join_buffer_size

Domyślna wartość to 256K. Minimalny rozmiar buforu używanego do skanowania zwykłego indeksu, skanowania indeksu zakresu i złączeń, które nie używają indeksów, a tym samym wykonują pełne skanowanie tabel. Używany również przez optymalizację BKA (która jest domyślnie wyłączona). Zwiększ jego wartość, aby uzyskać szybsze pełne złączenia, gdy dodawanie indeksów nie jest możliwe. Zastrzeżenie może jednak dotyczyć problemów z pamięcią, jeśli ustawisz to zbyt wysoko. Pamiętaj, że dla każdego pełnego sprzężenia między dwiema tabelami przydzielany jest jeden bufor złączeń. W przypadku złożonego sprzężenia między kilkoma tabelami, dla których nie są używane indeksy, może być konieczne użycie wielu buforów sprzężenia. Najlepiej pozostawić globalnie niski poziom i ustawić wysoki poziom w sesjach (za pomocą składni SET SESSION), które wymagają dużych pełnych złączeń. Na platformach 64-bitowych system Windows obcina wartości powyżej 4 GB do 4 GB-1 z ostrzeżeniem.

max_heap_table_size

Jest to maksymalny rozmiar w bajtach dla tabel MEMORY tworzonych przez użytkownika, które mogą rosnąć. Jest to przydatne, gdy aplikacja obsługuje tabele silnika pamięci masowej MEMORY. Ustawienie zmiennej, gdy serwer jest aktywny, nie ma wpływu na istniejące tabele, chyba że zostaną one odtworzone lub zmienione. Mniejszy z wartości max_heap_table_size i tmp_table_size ogranicza również wewnętrzne tabele w pamięci. Ta zmienna jest również w połączeniu z tmp_table_size, aby ograniczyć rozmiar wewnętrznych tabel w pamięci (różni się to od tabel utworzonych jawnie jako Engine=MEMORY, ponieważ stosuje tylko max_heap_table_size), w zależności od tego, która z nich jest mniejsza, jest stosowana między nimi.

tmp_table_size

Największy rozmiar tabel tymczasowych w pamięci (nie tabel MEMORY), chociaż jeśli max_heap_table_size jest mniejszy, będzie miał zastosowanie dolny limit. Jeśli tymczasowa tabela w pamięci przekracza limit, MySQL automatycznie konwertuje ją na tymczasową tabelę na dysku. Zwiększ wartość tmp_table_size (i max_heap_table_size, jeśli to konieczne), jeśli wykonujesz wiele zaawansowanych zapytań GROUP BY i masz dużą ilość dostępnej pamięci. Liczbę wewnętrznych tabel tymczasowych utworzonych na dysku można porównać z łączną liczbą utworzonych wewnętrznych tabel tymczasowych, porównując wartości zmiennych Created_tmp_disk_tables i Created_tmp_tables. W ClusterControl możesz to monitorować za pomocą pulpitu nawigacyjnego -> wykres obiektów tymczasowych.

table_open_cache

Możesz zwiększyć wartość tej zmiennej, jeśli masz dużą liczbę tabel, które są często używane w zestawie danych. Będzie on stosowany do wszystkich gwintów, czyli na podstawie połączenia. Wartość wskazuje maksymalną liczbę tabel, które serwer może pozostawić otwarte w jednej instancji pamięci podręcznej tabel. Chociaż zwiększanie tej wartości zwiększa liczbę deskryptorów plików wymaganych przez mysqld, więc równie dobrze możesz rozważyć sprawdzenie wartości open_files_limit lub sprawdzić, jak duży jest limit SOFT i HARD ustawiony w systemie operacyjnym *nix. Możesz monitorować to, czy chcesz zwiększyć pamięć podręczną tabel, sprawdzając zmienną stanu Opened_tables. Jeśli wartość Opened_tables jest duża i nie używasz często FLUSH TABLES (co tylko wymusza zamknięcie i ponowne otwarcie wszystkich tabel), należy zwiększyć wartość zmiennej table_open_cache. Jeśli masz małą wartość dla table_open_cache, a duża liczba tabel jest często używana, może to wpłynąć na wydajność serwera. Jeśli zauważysz wiele wpisów na liście procesów MySQL ze statusem „Otwieranie tabel” lub „Zamykanie tabel”, to czas dostosować wartość tej zmiennej, ale zwróć uwagę na wspomniane wcześniej zastrzeżenie. W ClusterControl możesz to sprawdzić w Pulpity nawigacyjne -> Stan otwartej pamięci podręcznej tabeli lub Pulpity nawigacyjne -> Otwarte tabele. Możesz to sprawdzić tutaj, aby uzyskać więcej informacji.

table_open_cache_instances

Ustawienie tej zmiennej pomogłoby poprawić skalowalność i oczywiście wydajność, co zmniejszyłoby rywalizację między sesjami. Ustawiona tutaj wartość ogranicza liczbę instancji pamięci podręcznej otwartych tabel. Pamięć podręczną otwartych tabel można podzielić na kilka mniejszych instancji pamięci podręcznej o rozmiarze table_open_cache / table_open_cache_instances . Sesja musi zablokować tylko jedną instancję, aby uzyskać do niej dostęp dla instrukcji DML. Powoduje to segmentację dostępu do pamięci podręcznej między instancjami, umożliwiając wyższą wydajność operacji korzystających z pamięci podręcznej, gdy istnieje wiele sesji uzyskujących dostęp do tabel. (Instrukcje DDL nadal wymagają blokady całej pamięci podręcznej, ale takie instrukcje są znacznie rzadsze niż instrukcje DML.) Wartość 8 lub 16 jest zalecana w systemach, które rutynowo używają 16 lub więcej rdzeni.

table_definition_cache

Buforuj definicje tabel, tj. w tym miejscu buforowane są CREATE TABLE, aby przyspieszyć otwieranie tabel i tylko jeden wpis na tabelę. Rozsądnie byłoby zwiększyć wartość, jeśli masz dużą liczbę tabel. Pamięć podręczna definicji tabeli zajmuje mniej miejsca i nie używa deskryptorów plików, w przeciwieństwie do normalnej pamięci podręcznej tabel. Peter Zaitsev z Percony sugeruje, czy możesz wypróbować ustawienie poniższej formuły,

The number of user-defined tables + 10% unless 50K+ tables

Pamiętaj jednak, że wartość domyślna jest oparta na następującej formule ograniczonej do limitu 2000.

MIN(400 + table_open_cache / 2, 2000)

Jeśli więc masz większą liczbę tabel w porównaniu do domyślnej, rozsądne jest zwiększenie jej wartości. Weź pod uwagę, że w przypadku InnoDB ta zmienna jest używana jako miękki limit liczby instancji otwartych tabel dla pamięci podręcznej słownika danych. Zastosuje mechanizm LRU, gdy przekroczy bieżącą wartość tej zmiennej. Limit pomaga rozwiązać sytuacje, w których znaczne ilości pamięci byłyby używane do buforowania rzadko używanych instancji tabel do następnego ponownego uruchomienia serwera. W związku z tym instancje tabel nadrzędnych i podrzędnych z relacjami kluczy obcych nie są umieszczane na liście LRU i mogą nakładać wyższy limit niż limit zdefiniowany przez table_definition_cache i nie podlegają wykluczeniu w pamięci podczas LRU. Dodatkowo, table_definition_cache definiuje miękki limit liczby obszarów tabel InnoDB file-per-table, które mogą być otwarte jednocześnie, co jest również kontrolowane przez innodb_open_files i w rzeczywistości używane jest najwyższe ustawienie między tymi zmiennymi, jeśli obie są ustawione . Jeśli żadna zmienna nie jest ustawiona, używana jest pamięć podręczna table_definition_cache, która ma wyższą wartość domyślną. Jeśli liczba uchwytów otwartych plików obszaru tabel przekracza limit zdefiniowany przez table_definition_cache lub innodb_open_files, mechanizm LRU przeszukuje listę LRU pliku obszaru tabel w poszukiwaniu plików, które zostały całkowicie opróżnione i nie są obecnie rozszerzane. Ten proces jest wykonywany za każdym razem, gdy otwierany jest nowy obszar tabel. Jeśli nie ma „nieaktywnych” przestrzeni tabel, żadne pliki przestrzeni tabel nie są zamykane. Miej to na uwadze.

max_allowed_packet

Jest to maksymalny rozmiar zwracanego zapytania SQL lub wiersza na połączenie. Wartość została ostatnio zwiększona w MySQL 5.6. Jednak w MySQL 8.0 (przynajmniej w wersji 8.0.3) aktualna wartość domyślna to 64 MiB. Możesz rozważyć dostosowanie tego, jeśli masz duże wiersze BLOB, które trzeba wyciągnąć (lub odczytać), w przeciwnym razie możesz pozostawić te domyślne ustawienia z 8.0, ale w starszych wersjach domyślnie jest to 4 MiB, więc możesz się tym zająć na wypadek, gdybyś napotkać błąd ER_NET_PACKET_TOO_LARGE. Największy możliwy pakiet, który można przesłać do lub z serwera lub klienta MySQL 8.0 to 1 GB.

skip_name_resolve Serwer MySQL obsługuje połączenia przychodzące na podstawie rozpoznawania nazw hostów. Domyślnie MySQL nie wyłącza żadnego rozpoznawania nazw hostów, co oznacza, że ​​przeprowadzi wyszukiwanie DNS i przez przypadek, jeśli DNS jest wolny, może to być przyczyną okropnej wydajności Twojej bazy danych. Rozważ włączenie tej opcji, jeśli nie potrzebujesz rozpoznawania DNS i skorzystaj z poprawy wydajności MySQL, gdy to wyszukiwanie DNS jest wyłączone. Weź pod uwagę, że ta zmienna nie jest dynamiczna, dlatego wymagane jest ponowne uruchomienie serwera, jeśli ustawisz to w pliku konfiguracyjnym MySQL. Możesz opcjonalnie uruchomić demona mysqld, przekazując opcję --skip-name-resolve, aby to włączyć.

max_connections

Jest to liczba dozwolonych połączeń dla Twojego serwera MySQL. Jeśli znajdziesz błąd w MySQL „Zbyt wiele połączeń”, możesz rozważyć ustawienie go wyżej. Domyślnie wartość 151 nie wystarcza, zwłaszcza na produkcyjnej bazie danych i biorąc pod uwagę, że masz większe zasoby serwera (nie marnuj zasobów serwera, zwłaszcza jeśli jest to dedykowany serwer MySQL). Musisz jednak mieć wystarczającą liczbę deskryptorów plików, w przeciwnym razie ich zabraknie. W takim przypadku rozważ dostosowanie limitów SOFT i HARD w systemach operacyjnych *nix i ustaw wyższą wartość open_files_limit w MySQL (5000 jest domyślnym limitem). Weź pod uwagę, że bardzo często aplikacja nie zamyka poprawnie połączeń z bazą danych, a ustawienie wysokiego max_connections może spowodować brak odpowiedzi lub duże obciążenie serwera. Użycie puli połączeń na poziomie aplikacji może pomóc w rozwiązaniu tego problemu.

thread_cache_size

To jest pamięć podręczna, która zapobiega nadmiernemu tworzeniu wątków. Gdy klient się rozłącza, wątki klienta są umieszczane w pamięci podręcznej, jeśli jest tam mniej niż wątków thread_cache_size. Żądania dotyczące wątków są zaspokajane przez ponowne wykorzystanie wątków pobranych z pamięci podręcznej, jeśli to możliwe, i tylko wtedy, gdy pamięć podręczna jest pusta, tworzony jest nowy wątek. Tę zmienną można zwiększyć, aby poprawić wydajność, jeśli masz dużo nowych połączeń. Zwykle nie zapewnia to znaczącej poprawy wydajności, jeśli masz dobrą implementację wątku. Jeśli jednak twój serwer widzi setki połączeń na sekundę, powinieneś normalnie ustawić wartość thread_cache_size na tyle, aby większość nowych połączeń używała wątków z pamięci podręcznej. Badając różnicę między zmiennymi stanu Connections i Threads_created, można zobaczyć, jak wydajna jest pamięć podręczna wątków. Używając wzoru podanego w dokumentacji, wystarczy 8 + (max_connections / 100).

query_cache_size

Dla niektórych ustawień ta zmienna jest ich największym wrogiem. W przypadku niektórych systemów, w których występuje duże obciążenie i są one zajęte wysokimi odczytami, ta zmienna ugrzęźnie. Pojawiły się benchmarki, które zostały dobrze przetestowane przez np. Perconę. Ta zmienna musi być ustawiona na 0 wraz z query_cache_type =0, aby ją wyłączyć. Dobrą wiadomością w MySQL 8.0 jest to, że zespół MySQL przestał to wspierać, ponieważ ta zmienna może naprawdę powodować problemy z wydajnością. Muszę zgodzić się na ich blogu, że raczej nie poprawi to przewidywalności działania. Jeśli jesteś zaangażowany w korzystanie z buforowania zapytań, sugeruję użycie Redis lub ProxySQL.

Silnik pamięci — InnoDB

InnoDB to silnik pamięci masowej zgodny z ACID z różnymi funkcjami do zaoferowania wraz z obsługą kluczy obcych (Declarative Referential Integrity). Jest tu wiele rzeczy do powiedzenia, ale pewne zmienne, które należy wziąć pod uwagę podczas strojenia:

innodb_buffer_pool_size

Ta zmienna działa jak bufor klucza MyISAM, ale ma wiele do zaoferowania. Ponieważ InnoDB w dużym stopniu opiera się na puli buforów, warto rozważyć ustawienie tej wartości zwykle na 70%-80% pamięci serwera. Korzystne jest również to, że masz większą przestrzeń pamięci niż zestaw danych i ustawiasz wyższą wartość dla swojej puli buforów, ale nie za dużo. W ClusterControl można to monitorować za pomocą naszych Dashboards -> InnoDB Metrics -> InnoDB Buffer Pool Pages graph. Możesz również monitorować to za pomocą POKAŻ STATUS GLOBALNY za pomocą zmiennych Innodb_buffer_pool_pages*.

innodb_buffer_pool_instances

W przypadku obciążenia współbieżności ustawienie tej zmiennej może poprawić współbieżność i zmniejszyć rywalizację, ponieważ różne wątki odczytu/zapisu stron w pamięci podręcznej. Minimalna wartość innodb_buffer_pool_instances powinna wynosić od 1 (minimum) do 64 (maksimum). Każda strona przechowywana lub odczytywana z puli buforów jest losowo przypisywana do jednej z instancji puli buforów za pomocą funkcji mieszającej. Każda pula buforów zarządza własnymi wolnymi listami, listami opróżniającymi, LRU i wszystkimi innymi strukturami danych podłączonymi do puli buforów i jest chroniona przez własny muteks puli buforów. Zwróć uwagę, że ta opcja działa tylko wtedy, gdy innodb_buffer_pool_size>=1GiB i jej rozmiar jest podzielony między instancje puli buforów.

innodb_log_file_size

Ta zmienna jest plikiem dziennika w grupie dzienników. Łączny rozmiar plików dziennika (innodb_log_file_size * innodb_log_files_in_group) nie może przekroczyć maksymalnej wartości, która jest nieco mniejsza niż 512 GB. Według Vadima większy rozmiar pliku dziennika jest lepszy dla wydajności, ale ma wadę (poważną), o którą trzeba się martwić:czas odzyskiwania po awarii. Należy zrównoważyć czas odzyskiwania w rzadkich przypadkach odzyskiwania po awarii z maksymalizacją przepustowości podczas szczytowych operacji. To ograniczenie może przełożyć się na 20-krotnie dłuższy proces odzyskiwania po awarii!

Aby to rozwinąć, większa wartość byłaby dobra dla dzienników transakcji InnoDB i ma kluczowe znaczenie dla dobrej i stabilnej wydajności zapisu. Im większa wartość, tym mniej aktywności opróżniania punktu kontrolnego jest wymagane w puli buforów, co pozwala na zapisanie operacji we/wy dysku. Jednak proces odzyskiwania jest dość powolny, gdy baza danych została nienormalnie zamknięta (awaria lub śmierć, albo OOM, albo przypadkowo). Idealnie możesz mieć 1-2GiB w produkcji, ale oczywiście możesz to dostosować. Analiza porównawcza tych zmian może być wielką zaletą, aby zobaczyć, jak działa, zwłaszcza po awarii.

innodb_log_buffer_size

Aby zapisać we/wy dysku, InnoDB zapisuje dane zmiany w buforze dziennika lt i używa wartości innodb_log_buffer_size, która ma domyślną wartość 8MiB. Jest to korzystne zwłaszcza w przypadku dużych transakcji, ponieważ nie trzeba zapisywać dziennika zmian na dysku przed zatwierdzeniem transakcji. Jeśli twój ruch związany z zapisem jest zbyt duży (wstawianie, usuwanie, aktualizacje), zwiększenie bufora oszczędza dyskowe operacje wejścia/wyjścia.

innodb_flush_log_at_trx_commit

Gdy innodb_flush_log_at_trx_commit jest ustawione na 1, bufor dziennika jest opróżniany przy każdym zatwierdzeniu transakcji do pliku dziennika na dysku i zapewnia maksymalną integralność danych, ale ma również wpływ na wydajność. Ustawienie jej na 2 oznacza, że ​​bufor dziennika jest opróżniany do pamięci podręcznej plików systemu operacyjnego przy każdym zatwierdzeniu transakcji. Implikacja 2 jest optymalna i poprawia wydajność, jeśli możesz złagodzić wymagania dotyczące ACID i możesz pozwolić sobie na utratę transakcji przez ostatnią sekundę lub dwie w przypadku awarii systemu operacyjnego.

innodb_thread_concurrency

Wraz z ulepszeniami silnika InnoDB zaleca się, aby silnik mógł kontrolować współbieżność poprzez utrzymywanie jej wartości domyślnej (która wynosi zero). Jeśli widzisz problemy ze współbieżnością, możesz dostroić tę zmienną. Zalecana wartość to dwukrotność liczby procesorów plus liczba dysków. To dynamiczna zmienna oznacza, że ​​można ją ustawić bez ponownego uruchamiania serwera MySQL.

innodb_flush_method

Ta zmienna musi być jednak wypróbowana i przetestowana na jakim sprzęcie najlepiej do Ciebie pasuje. Jeśli używasz macierzy RAID z pamięcią podręczną podtrzymywaną bateryjnie, DIRECT_IO pomaga zmniejszyć ciśnienie we/wy. Bezpośrednie we/wy nie jest buforowane, dzięki czemu unika się podwójnego buforowania z pulą buforów i pamięcią podręczną systemu plików. Jeśli twój dysk jest przechowywany w SAN, O_DSYNC może być szybszy w przypadku dużego obciążenia odczytu z głównie instrukcjami SELECT.

innodb_file_per_table

innodb_file_per_table jest domyślnie WŁĄCZONE od MySQL 5.6. Jest to zwykle zalecane, ponieważ pozwala uniknąć ogromnej wspólnej przestrzeni tabel i umożliwia odzyskanie miejsca po upuszczeniu lub przycięciu tabeli. Oddzielna przestrzeń tabel jest również korzystna dla schematu częściowej kopii zapasowej Xtrabackup.

innodb_stats_on_metadata

Próbuje to utrzymać pod kontrolą procent brudnych stron, a przed wtyczką Innodb był to naprawdę jedyny sposób na dostrojenie opróżniania brudnego bufora. Jednak widziałem serwery z 3% brudnymi buforami i osiągają maksymalny wiek w punkcie kontrolnym. Sposób, w jaki zwiększa to opróżnianie brudnego bufora, również nie skaluje się dobrze na podsystemach z wysokimi io, skutecznie podwaja opróżnianie brudnego bufora na sekundę, gdy % brudnych stron przekracza tę ilość.

innodb_io_capacity

To ustawienie, pomimo naszych wielkich nadziei, że pozwoli Innodb lepiej wykorzystać nasze IO we wszystkich operacjach, po prostu kontroluje ilość opróżniania brudnej strony na sekundę (i inne zadania w tle, takie jak odczyt z wyprzedzeniem). Zwiększ to, więcej spłukujesz na sekundę. To się nie dostosowuje, po prostu wykonuje tyle iopów na sekundę, jeśli są brudne bufory do opróżnienia. Skutecznie wyeliminuje jakąkolwiek optymalizację konsolidacji we/wy, jeśli masz wystarczająco małe obciążenie zapisu (to znaczy, że brudne strony są opróżniane niemal natychmiast, w tym przypadku może być lepiej bez dziennika transakcji). Może również szybko zagłodzić odczyty i zapisy danych w dzienniku transakcji, jeśli ustawisz to zbyt wysoko.

innodb_write_io_threads

Kontroluje liczbę wątków, które będą miały zapisy na dysku w toku. Nie jestem pewien, dlaczego jest to nadal przydatne, jeśli możesz korzystać z natywnego AIO systemu Linux. Mogą one również stać się bezużyteczne przez systemy plików, które nie pozwalają na równoległe zapisywanie do tego samego pliku przez więcej niż jeden wątek (szczególnie, jeśli masz stosunkowo mało tabel i/lub używasz globalnych obszarów tabel)

innodb_adaptive_flushing

Określa, czy dynamicznie dostosowywać szybkość opróżniania zabrudzonych stron w puli buforów InnoDB na podstawie obciążenia. Dynamiczne dostosowywanie szybkości spłukiwania ma na celu uniknięcie nagłych wzrostów aktywności we/wy. Zazwyczaj jest to domyślnie włączone . Ta zmienna, gdy jest włączona, stara się sprytniej opróżniać bardziej agresywnie w oparciu o liczbę brudnych stron i tempo wzrostu dziennika transakcji.

innodb_dedicated_server

Ta zmienna jest nowością w MySQL 8.0, która jest stosowana globalnie i wymaga ponownego uruchomienia MySQL, ponieważ nie jest zmienną dynamiczną. Jednak, jak podaje dokumentacja, ta zmienna powinna być włączona tylko wtedy, gdy twój MySQL działa na dedykowanym serwerze. W przeciwnym razie nie włączaj tego na współdzielonym hoście ani nie udostępniaj zasobów systemowych innym aplikacjom. Gdy ta opcja jest włączona, InnoDB wykona automatyczną konfigurację ilości pamięci wykrytej dla zmiennych innodb_buffer_pool_size, innodb_log_file_size, innodb_flush_method. Jedynym minusem jest to, że nie ma możliwości zastosowania żądanych wartości do wspomnianych wykrytych zmiennych.

MyISAM

key_buffer_size

InnoDB jest obecnie domyślnym silnikiem pamięci masowej MySQL, domyślną wartość key_buffer_size można prawdopodobnie zmniejszyć, chyba że produktywnie używasz MyISAM jako części swojej aplikacji (ale kto używa teraz MyISAM w produkcji?). Sugerowałbym tutaj ustawienie około 1% pamięci RAM lub 256 MiB na początku, jeśli masz większą pamięć i przeznacz pozostałą pamięć na pamięć podręczną systemu operacyjnego i pulę buforów InnoDB.

Inne postanowienia dotyczące wydajności

slow_query_log

Oczywiście ta zmienna nie pomaga w rozbudowie serwera MySQL. Jednak ta zmienna może pomóc w analizie wolno działających zapytań. Wartość można ustawić na 0 lub OFF, aby wyłączyć rejestrowanie. Ustawienie go na 1 lub ON, aby to umożliwić. Wartość domyślna zależy od tego, czy podano opcję --slow_query_log. Miejsce docelowe wyjścia dziennika jest kontrolowane przez zmienną systemową log_output; jeśli ta wartość wynosi NONE, żadne wpisy dziennika nie są zapisywane, nawet jeśli dziennik jest włączony. Możesz ustawić nazwę pliku lub miejsce docelowe pliku dziennika zapytań, ustawiając zmienną slow_query_log_file.

long_query_time

Jeśli zapytanie trwa dłużej niż tyle sekund, serwer zwiększa wartość zmiennej statusu Slow_queries. Jeśli włączony jest dziennik powolnych zapytań, zapytanie jest rejestrowane w pliku dziennika powolnych zapytań. Ta wartość jest mierzona w czasie rzeczywistym, a nie w czasie procesora, więc zapytanie, które jest poniżej progu w słabo obciążonym systemie, może być powyżej progu w mocno obciążonym systemie. Minimalna i domyślna wartość long_query_time to odpowiednio 0 i 10. Zwróć też uwagę, że jeśli zmienna min_examined_row_limit jest ustawiona na> 0, nie będzie rejestrować zapytań, nawet jeśli zajmie to zbyt dużo czasu, jeśli liczba zwróconych wierszy jest mniejsza niż wartość ustawiona w min_examined_row_limit.

Aby uzyskać więcej informacji na temat dostrajania powolnego rejestrowania zapytań, zapoznaj się z dokumentacją tutaj.

sync_binlog

Ta zmienna kontroluje, jak często MySQL będzie synchronizować binlogi z dyskiem. Domyślnie (>=5.7.7) jest to ustawione na 1, co oznacza synchronizację z dyskiem przed zatwierdzeniem transakcji. Jednak ma to negatywny wpływ na wydajność ze względu na zwiększoną liczbę zapisów. Ale jest to najbezpieczniejsze ustawienie, jeśli chcesz, aby wraz ze swoimi niewolnikami był ściśle zgodny z kwasem. Alternatywnie możesz ustawić to na 0, jeśli chcesz wyłączyć synchronizację dysku i po prostu polegać na systemie operacyjnym, aby od czasu do czasu opróżniać dziennik binarny na dysk. Ustawienie wartości większej niż 1 oznacza, że ​​dziennik binarny jest synchronizowany z dyskiem po zebraniu N grup zatwierdzania dziennika binarnego, gdzie N wynosi> 1.

Zrzuć/przywróć pulę buforów

Często zdarza się, że produkcyjna baza danych musi się rozgrzać po zimnym starcie/restartowaniu. Zrzucając bieżącą pulę buforów przed ponownym uruchomieniem, zapisałoby to zawartość z puli buforów, a po jej uruchomieniu załaduje zawartość z powrotem do puli buforów. W ten sposób unika się konieczności ponownego nagrzewania bazy danych do pamięć podręczna. Zwróć uwagę, że ta wersja została wprowadzona w 5.6, ale Percona Server 5.5 jest już dostępna, na wypadek gdybyś się zastanawiał. Aby włączyć tę funkcję, ustaw obie zmienne innodb_buffer_pool_dump_at_shutdown =ON i innodb_buffer_pool_load_at_startup =ON.

Sprzęt

Jesteśmy teraz w 2019 roku, wprowadzono wiele nowych ulepszeń sprzętowych. Zazwyczaj nie ma twardych wymagań, aby MySQL wymagał określonego sprzętu, ale zależy to od tego, do czego potrzebujesz bazy danych. Spodziewam się, że nie czytasz tego bloga, ponieważ przeprowadzasz test, jeśli działa on na procesorze Intel Pentium 200 MHz.

W przypadku CPU szybsze procesory z wieloma rdzeniami będą optymalne dla MySQL w najnowszych wersjach, co najmniej od 5.6. Procesory Intel Xeon/Itanium mogą być drogie, ale przetestowane pod kątem skalowalnych i niezawodnych platform komputerowych. Amazon dostarcza swoje instancje EC2 działające w architekturze ARM. Chociaż osobiście nie próbowałem uruchamiać ani nie przypominać sobie uruchamiania MySQL na architekturze ARM, istnieją testy porównawcze stworzone lata temu. Nowoczesne procesory mogą skalować swoje częstotliwości w górę i w dół w oparciu o temperaturę, obciążenie i zasady oszczędzania energii systemu operacyjnego. Istnieje jednak szansa, że ​​ustawienia procesora w systemie operacyjnym Linux są ustawione na inny regulator. Możesz to sprawdzić lub ustawić za pomocą regulatora „wydajności”, wykonując następujące czynności:

echo performance | sudo tee /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_governor

W przypadku pamięci bardzo ważne jest, aby pamięć była duża i mogła równać się rozmiarowi zestawu danych. Upewnij się, że masz swappiness =1. Możesz to sprawdzić sprawdzając sysctl lub sprawdzając plik w procfs. Można to osiągnąć, wykonując następujące czynności:

$ sysctl -e vm.swappiness
vm.swappiness = 1

Lub ustawiając go na wartość 1 w następujący sposób

$ sudo sysctl vm.swappiness=1
vm.swappiness = 1

Kolejną świetną rzeczą do rozważenia przy zarządzaniu pamięcią jest rozważenie wyłączenia THP (Transparrent Huge Pages). Przypominam sobie, że w przeszłości napotkaliśmy dziwne problemy z wykorzystaniem procesora i myśleliśmy, że jest to spowodowane dyskowymi operacjami we/wy. Okazało się, że problem tkwił w wątku khugepaged jądra, który dynamicznie przydziela pamięć w czasie wykonywania. Mało tego, podczas gdy jądro przechodzi do defragmentacji, twoja pamięć zostanie szybko przydzielona, ​​ponieważ przekazuje ją do THP. Standardowa pamięć HugePages jest wstępnie przydzielana podczas uruchamiania i nie zmienia się w czasie wykonywania. Możesz to zweryfikować i wyłączyć, wykonując następujące czynności:

$ cat /sys/kernel/mm/transparent_hugepage/enabled
$ echo "never" > /sys/kernel/mm/transparent_hugepage/enabled

W przypadku dysku ważna jest dobra przepustowość. Korzystanie z RAID10 jest najlepszą konfiguracją bazy danych z bateryjną jednostką podtrzymującą. Wraz z pojawieniem się dysków flash, które oferują wysoką przepustowość dysku i wysokie dyskowe operacje we/wy do odczytu/zapisu, ważne jest, aby był w stanie zarządzać wysokim wykorzystaniem dysku i dyskowymi operacjami we/wy.

System operacyjny

Większość systemów produkcyjnych działających na MySQL działa w systemie Linux. Dzieje się tak dlatego, że MySQL został przetestowany i przetestowany na Linuksie i brzmi, że jest de facto standardem dla instalacji MySQL. Jednak oczywiście nic nie stoi na przeszkodzie, aby używać go na platformie Unix lub Windows. Byłoby łatwiej, gdyby Twoja platforma została przetestowana i byłaby szeroka społeczność, która pomoże, na wypadek problemów. Większość instalacji działa na systemach RHEL/Centos/Fedora i Debian/Ubuntu. W AWS Amazon ma swój Amazon Linux, który, jak widzę, jest używany przez niektórych w produkcji.

Najważniejszym do rozważenia przy konfiguracji jest to, że twój system plików używa XFS lub Ext4. Na pewno są plusy i minusy między tymi dwoma systemami plików, ale nie będę tutaj przechodził do szczegółów. Niektórzy twierdzą, że XFS przewyższa Ext4, ale są też doniesienia, że ​​Ext4 przewyższa XFS. ZFS również wychodzi z obrazu jako dobry kandydat na alternatywny system plików. Jervin Real (z Percony) ma świetne źródło informacji na ten temat, możesz sprawdzić tę prezentację podczas konferencji ZFS.

Linki zewnętrzne

https://developer.okta.com/blog/2015/05/22/tcmalloc

https://www.percona.com/blog/2012/07/05/impact-of-memory-allocators-on-mysql-performance/

https://www.percona.com/live/18/sessions/benchmark-noise-reduction-jak-konfigurować-maszyny-do-stabilnych-wyników

https://zfs.datto.com/2018_slides/real.pdf

https://docs.oracle.com/en/database/oracle/oracle-database/12.2/ladbi/disabling-transparent-hugepages.html#GUID-02E9147D-D565-4AF8-B12A-8E6E9F74BEEA


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak zaktualizować wiele kolumn w MySQL

  2. Jak wypełnić dziury w polach autoinkrementacji?

  3. Policz wiersze tabeli

  4. Jaki jest odpowiednik MySQL funkcji CHOOSE() w SQL Server?

  5. Funkcja agregująca w MySQL - lista (jak LITAGG w Oracle)