Rozwiązywanie problemów z wydajnością zapytań w usłudze Azure Database for MySQL — serwer elastyczny

DOTYCZY: Azure Database for MySQL — pojedynczy serwer usługi Azure Database for MySQL — serwer elastyczny

Ważne

Pojedynczy serwer usługi Azure Database for MySQL znajduje się na ścieżce wycofania. Zdecydowanie zalecamy uaktualnienie do serwera elastycznego usługi Azure Database for MySQL. Aby uzyskać więcej informacji na temat migracji do serwera elastycznego usługi Azure Database for MySQL, zobacz Co się dzieje z usługą Azure Database for MySQL — pojedynczy serwer?

Wydajność zapytań może mieć wpływ na wiele czynników, dlatego najpierw należy przyjrzeć się zakresowi objawów, które występują w wystąpieniu serwera elastycznego usługi Azure Database for MySQL. Na przykład wydajność zapytań jest niska dla:

  • Wszystkie zapytania uruchomione w wystąpieniu serwera elastycznego usługi Azure Database for MySQL?
  • Konkretny zestaw zapytań?
  • Konkretne zapytanie?

Należy również pamiętać, że wszelkie ostatnie zmiany struktury lub danych bazowych tabel, które wysyłasz zapytania, mogą mieć wpływ na wydajność.

Włączanie funkcji rejestrowania

Przed przeanalizowaniem poszczególnych zapytań należy zdefiniować testy porównawcze zapytań. Dzięki tym informacjom można zaimplementować funkcję rejestrowania na serwerze bazy danych w celu śledzenia zapytań przekraczających określony próg na podstawie potrzeb aplikacji.

Usługa Azure Database for MySQL — serwer elastyczny, zaleca się używanie funkcji dziennika wolnych zapytań do identyfikowania zapytań, które trwa dłużej niż N sekund. Po zidentyfikowaniu zapytań z dziennika wolnych zapytań możesz użyć diagnostyki MySQL do rozwiązywania problemów z tymi zapytaniami.

Przed rozpoczęciem śledzenia długotrwałych zapytań należy włączyć slow_query_log parametr przy użyciu witryny Azure Portal lub interfejsu wiersza polecenia platformy Azure. Po włączeniu tego parametru należy również skonfigurować wartość parametru long_query_time , aby określić liczbę sekund, które zapytania mogą być uruchamiane przed zidentyfikowaniem jako "wolno działające" zapytania. Wartość domyślna parametru to 10 sekund, ale możesz dostosować wartość, aby zaspokoić potrzeby umowy SLA aplikacji.

Azure Database for MySQL flexible server slow query log interface.

Dziennik wolnych zapytań jest doskonałym narzędziem do śledzenia długotrwałych zapytań, ale istnieją pewne scenariusze, w których może nie być skuteczne. Na przykład dziennik wolnych zapytań:

  • Negatywnie wpływa na wydajność, jeśli liczba zapytań jest bardzo wysoka lub jeśli instrukcja zapytania jest bardzo duża. Odpowiednio dostosuj wartość parametru long_query_time .
  • Może nie być pomocne, jeśli włączono log_queries_not_using_index również parametr , który określa, że zapytania dziennika mają pobierać wszystkie wiersze. Zapytania wykonujące pełne skanowanie indeksu korzystają z indeksu, ale zostałyby zarejestrowane, ponieważ indeks nie ogranicza liczby zwracanych wierszy.

Pobieranie informacji z dzienników

Dzienniki są dostępne przez maksymalnie siedem dni od ich utworzenia. Dzienniki wolnych zapytań można wyświetlić i pobrać za pośrednictwem witryny Azure Portal lub interfejsu wiersza polecenia platformy Azure. W witrynie Azure Portal przejdź do serwera, w obszarze Monitorowanie wybierz pozycję Dzienniki serwera, a następnie wybierz strzałkę w dół obok wpisu, aby pobrać dzienniki skojarzone z datą i godziną badania.

Azure Database for MySQL flexible server retrieving data from the logs.

Ponadto, jeśli dzienniki wolnych zapytań są zintegrowane z dziennikami usługi Azure Monitor za pośrednictwem dzienników diagnostycznych, możesz uruchamiać zapytania w edytorze, aby je dokładniej analizować:

AzureDiagnostics
| where Resource == '<your server name>'
| where Category == 'MySqlSlowLogs'
| project TimeGenerated, Resource , event_class_s, start_time_t , query_time_d, sql_text_s
| where query_time_d > 10

Uwaga

Aby uzyskać więcej przykładów, aby rozpocząć diagnozowanie dzienników wolnych zapytań za pomocą dzienników diagnostycznych, zobacz Analizowanie dzienników w dziennikach usługi Azure Monitor.

Poniższa migawka przedstawia przykładowe powolne zapytanie.

# Time: 2021-11-13T10:07:52.610719Z
# User@Host: root[root] @  [172.30.209.6]  Id: 735026
# Query_time: 25.314811  Lock_time: 0.000000 Rows_sent: 126  Rows_examined: 443308
use employees;
SET timestamp=1596448847;
select * from titles where DATE(from_date) > DATE('1994-04-05') AND title like '%senior%';;

Zwróć uwagę, że zapytanie działało w ciągu 26 sekund, zbadało ponad 443 tys. wierszy i zwróciło 126 wierszy wyników.

Zazwyczaj należy skoncentrować się na zapytaniach o wysokich wartościach dla Query_time i Rows_examined. Jeśli jednak zauważysz zapytania o wysokim Query_time, ale tylko kilka Rows_examined, często wskazuje to na obecność wąskiego gardła zasobów. W takich przypadkach należy sprawdzić, czy występuje ograniczenie operacji we/wy lub użycie procesora CPU.

Profilowanie zapytania

Po zidentyfikowaniu określonego wolno działającego zapytania możesz użyć polecenia EXPLAIN i profilowania, aby zebrać więcej szczegółów.

Aby sprawdzić plan zapytania, uruchom następujące polecenie:

EXPLAIN <QUERY>

Uwaga

Aby uzyskać więcej informacji na temat używania instrukcji EXPLAIN, zobacz How to use EXPLAIN to profile query performance in Azure Database for MySQL flexible server (Jak używać funkcji EXPLAIN do profilowania wydajności zapytań na serwerze elastycznym usługi Azure Database for MySQL).

Oprócz utworzenia planu EXPLAIN dla zapytania można użyć polecenia SHOW PROFILE, które umożliwia diagnozowanie wykonywania instrukcji, które zostały uruchomione w bieżącej sesji.

Aby włączyć profilowanie i profilowanie określonego zapytania w sesji, uruchom następujący zestaw poleceń:

SET profiling = 1;
<QUERY>;
SHOW PROFILES;
SHOW PROFILE FOR QUERY <X>;

Uwaga

Profilowanie poszczególnych zapytań jest dostępne tylko w sesji, a instrukcje historyczne nie mogą być profilowane.

Przyjrzyjmy się bliżej użyciu tych poleceń do profilowania zapytania. Najpierw włącz profilowanie dla bieżącej sesji, uruchom SET PROFILING = 1 polecenie:

mysql> SET PROFILING = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

Następnie wykonaj nieoptymalne zapytanie, które wykonuje pełne skanowanie tabeli:

mysql> select * from sbtest8 where c like '%99098187165%';
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k       | c                                                                                                                       | pad                                                         |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| 10 | 5035785 | 81674956652-89815953173-84507133182-62502329576-99098187165-62672357237-37910808188-52047270287-89115790749-78840418590 | 91637025586-81807791530-84338237594-90990131533-07427691758 |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
1 row in set (27.60 sec)

Następnie wyświetl listę wszystkich dostępnych profilów zapytań, uruchamiając SHOW PROFILES polecenie :

mysql> SHOW PROFILES;
+----------+-------------+----------------------------------------------------+
| Query_ID | Duration    | Query                                              |
+----------+-------------+----------------------------------------------------+
|        1 | 27.59450000 | select * from sbtest8 where c like '%99098187165%' |
+----------+-------------+----------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

Na koniec, aby wyświetlić profil zapytania 1, uruchom SHOW PROFILE FOR QUERY 1 polecenie .

mysql> SHOW PROFILE FOR QUERY 1;
+----------------------+-----------+
| Status               | Duration  |
+----------------------+-----------+
| starting             |  0.000102 |
| checking permissions |  0.000028 |
| Opening tables       |  0.000033 |
| init                 |  0.000035 |
| System lock          |  0.000018 |
| optimizing           |  0.000017 |
| statistics           |  0.000025 |
| preparing            |  0.000019 |
| executing            |  0.000011 |
| Sending data         | 27.594038 |
| end                  |  0.000041 |
| query end            |  0.000014 |
| closing tables       |  0.000013 |
| freeing items        |  0.000088 |
| cleaning up          |  0.000020 |
+----------------------+-----------+
15 rows in set, 1 warning (0.00 sec)

Wyświetlanie listy najczęściej używanych zapytań na serwerze bazy danych

Za każdym razem, gdy rozwiązujesz problemy z wydajnością zapytań, warto zrozumieć, które zapytania są najczęściej uruchamiane w wystąpieniu serwera elastycznego usługi Azure Database for MySQL. Możesz użyć tych informacji, aby ocenić, czy którekolwiek z najważniejszych zapytań trwa dłużej niż zwykle. Ponadto deweloper lub administrator baz danych może użyć tych informacji, aby określić, czy jakiekolwiek zapytanie ma nagły wzrost liczby i czasu trwania wykonywania zapytań.

Aby wyświetlić listę 10 najczęściej wykonywanych zapytań względem wystąpienia serwera elastycznego usługi Azure Database for MySQL, uruchom następujące zapytanie:

SELECT digest_text AS normalized_query,
 count_star AS all_occurrences,
 Concat(Round(sum_timer_wait / 1000000000000, 3), ' s') AS total_time,
 Concat(Round(min_timer_wait / 1000000000000, 3), ' s') AS min_time,
 Concat(Round(max_timer_wait / 1000000000000, 3), ' s') AS max_time,
 Concat(Round(avg_timer_wait / 1000000000000, 3), ' s') AS avg_time,
 Concat(Round(sum_lock_time / 1000000000000, 3), ' s') AS total_locktime,
 sum_rows_affected AS sum_rows_changed,
 sum_rows_sent AS sum_rows_selected,
 sum_rows_examined AS sum_rows_scanned,
 sum_created_tmp_tables,
 sum_select_scan,
 sum_no_index_used,
 sum_no_good_index_used
FROM performance_schema.events_statements_summary_by_digest
ORDER BY sum_timer_wait DESC LIMIT 10;

Uwaga

Użyj tego zapytania, aby przeprowadzić test porównawczy zapytań wykonywanych na serwerze bazy danych i określić, czy w pierwszych zapytaniach nastąpiła zmiana lub czy w początkowym tezie zapytania wzrosły czas trwania uruchamiania.

Wyświetlanie listy 10 najdroższych zapytań według łącznego czasu wykonywania

Dane wyjściowe z poniższego zapytania zawierają informacje o 10 pierwszych zapytaniach uruchomionych na serwerze bazy danych i ich liczbie wykonań na serwerze bazy danych. Udostępnia również inne przydatne informacje, takie jak opóźnienia zapytań, czasy ich blokady, liczba tabel tymczasowych utworzonych w ramach środowiska uruchomieniowego zapytań itp. Użyj tych danych wyjściowych zapytania, aby śledzić najważniejsze zapytania w bazie danych i zmiany czynników, takich jak opóźnienia, co może wskazywać na szansę dalszego dostosowania zapytania, aby uniknąć wszelkich przyszłych zagrożeń.

SELECT REPLACE(event_name, 'statement/sql/', '') AS statement, 
 count_star AS all_occurrences , 
 Concat(Round(sum_timer_wait / 1000000000000, 2), ' s') AS total_latency, 
 Concat(Round(avg_timer_wait / 1000000000000, 2), ' s') AS avg_latency, 
 Concat(Round(sum_lock_time / 1000000000000, 2), ' s') AS total_lock_time  , 
 sum_rows_affected AS sum_rows_changed, 
 sum_rows_sent AS  sum_rows_selected, 
 sum_rows_examined AS  sum_rows_scanned, 
 sum_created_tmp_tables,  sum_created_tmp_disk_tables, 
 IF(sum_created_tmp_tables = 0, 0, Concat( Truncate(sum_created_tmp_disk_tables / 
 sum_created_tmp_tables * 100, 0))) AS 
 tmp_disk_tables_percent, 
 sum_select_scan, 
 sum_no_index_used, 
 sum_no_good_index_used 
FROM performance_schema.events_statements_summary_global_by_event_name 
WHERE event_name LIKE 'statement/sql/%' 
 AND count_star > 0 
ORDER BY sum_timer_wait DESC 
LIMIT 10;

Monitorowanie odzyskiwania pamięci w usłudze InnoDB

Gdy odzyskiwanie pamięci w usłudze InnoDB jest zablokowane lub opóźnione, baza danych może opracować znaczne opóźnienie czyszczenia, które może negatywnie wpłynąć na wykorzystanie magazynu i wydajność zapytań.

Długość listy historii wycofywania w usłudze InnoDB (HLL) mierzy liczbę rekordów zmian przechowywanych w dzienniku cofania. Rosnąca wartość HLL wskazuje, że wątki odzyskiwania pamięci w usłudze InnoDB (wątki przeczyszczania) nie nadążają za obciążeniem zapisu lub że czyszczenie jest blokowane przez długotrwałe zapytanie lub transakcję.

Nadmierne opóźnienia w wyrzucaniu pamięci mogą mieć poważne, negatywne konsekwencje:

  • Przestrzeń tabel systemu InnoDB zostanie rozwinięta, co przyspiesza wzrost bazowego woluminu magazynu. Czasami przestrzeń tabel systemowych może pęcznieć o kilka terabajtów w wyniku zablokowanego przeczyszczenia.
  • Rekordy oznaczone znacznikami usuwania nie zostaną usunięte w odpowiednim czasie. Może to spowodować, że przestrzenie tabel InnoDB rosną i uniemożliwiają ponowne wykorzystanie magazynu zajmowanego przez te rekordy przez aparat.
  • Wydajność wszystkich zapytań może ulec pogorszeniu, a wykorzystanie procesora CPU może wzrosnąć z powodu wzrostu struktur magazynu InnoDB.

W rezultacie ważne jest monitorowanie wartości, wzorców i trendów HLL.

Znajdowanie wartości HLL

Wartość HLL można znaleźć, uruchamiając polecenie stanu innodb aparatu show. Wartość zostanie wyświetlona w danych wyjściowych w obszarze nagłówka TRANSAKCJE:

mysql> show engine innodb status\G 
*************************** 1. row *************************** 
 
(...) 
 
------------ 
TRANSACTIONS 
------------ 
Trx id counter 52685768 
Purge done for trx's n:o < 52680802 undo n:o < 0 state: running but idle 
History list length 2964300 
 
(...) 

Możesz również określić wartość HLL, wykonując zapytanie względem tabeli information_schema.innodb_metrics:

mysql> select count from information_schema.innodb_metrics  
    -> where name = 'trx_rseg_history_len'; 
+---------+ 
|  count  | 
+---------+ 
| 2964300 | 
+---------+ 
1 row in set (0.00 sec)

Interpretowanie wartości HLL

Podczas interpretowania wartości HLL należy wziąć pod uwagę wytyczne wymienione w poniższej tabeli:

Wartość Uwagi
Mniej niż ~10 000 Normalne wartości wskazujące, że odzyskiwanie pamięci nie spada z tyłu.
Od ~10 000 do ~1 000 000 Te wartości wskazują niewielkie opóźnienie w wyrzucaniu pamięci. Takie wartości mogą być dopuszczalne, jeśli pozostają stałe i nie zwiększają się.
Większe niż ~1000 000 Te wartości należy zbadać i mogą wymagać akcji naprawczych

Rozwiązywanie problemów z nadmierną wartością HLL

Jeśli usługa HLL pokazuje duże skoki lub wykazuje wzorzec okresowego wzrostu, natychmiast zbadaj zapytania i transakcje uruchomione w wystąpieniu serwera elastycznego usługi Azure Database for MySQL. Następnie możesz rozwiązać wszelkie problemy z obciążeniem, które mogą uniemożliwiać postęp procesu odzyskiwania pamięci. Chociaż nie oczekuje się, że baza danych będzie wolna od opóźnienia przeczyszczania, nie można pozwolić, aby opóźnienie rosło niekontrolowanie.

Aby uzyskać informacje o transakcji z information_schema.innodb_trx tabeli, na przykład uruchom następujące polecenia:

select * from information_schema.innodb_trx  
order by trx_started asc\G

Szczegóły w kolumnie trx_started ułatwią obliczenie wieku transakcji.

mysql> select * from information_schema.innodb_trx  
    -> order by trx_started asc\G 
*************************** 1. row *************************** 
                    trx_id: 8150550 
                 trx_state: RUNNING 
               trx_started: 2021-11-13 20:50:11 
     trx_requested_lock_id: NULL 
          trx_wait_started: NULL 
                trx_weight: 0 
       trx_mysql_thread_id: 19 
                 trx_query: select * from employees where DATE(hire_date) > DATE('1998-04-05') AND first_name like '%geo%';
(…) 

Aby uzyskać informacje na temat bieżących sesji bazy danych, w tym czasu spędzonego w bieżącym stanie sesji, sprawdź tabelę information_schema.processlist . Na przykład następujące dane wyjściowe pokazują sesję, która aktywnie wykonuje zapytanie w ciągu ostatnich 1462 sekund:

mysql> select user, host, db, command, time, info  
    -> from information_schema.processlist  
    -> order by time desc\G 
*************************** 1. row *************************** 
   user: test 
   host: 172.31.19.159:38004 
     db: employees 
command: Query 
   time: 1462 
   info: select * from employees where DATE(hire_date) > DATE('1998-04-05') AND first_name like '%geo%';
 
(...) 

Zalecenia

  • Upewnij się, że baza danych ma wystarczającą ilość zasobów przydzielonych do uruchamiania zapytań. Czasami może być konieczne skalowanie w górę rozmiaru wystąpienia, aby uzyskać więcej rdzeni procesora CPU i dodatkowej pamięci, aby obsłużyć obciążenie.

  • Unikaj dużych lub długotrwałych transakcji, dzieląc je na mniejsze transakcje.

  • Skonfiguruj innodb_purge_threads zgodnie z obciążeniem, aby zwiększyć wydajność operacji przeczyszczania w tle.

    Uwaga

    Przetestuj wszelkie zmiany w tej zmiennej serwera dla każdego środowiska, aby ocenić zmianę zachowania aparatu.

  • Użyj alertów dotyczących wartości "Procent procesora CPU hosta", "Procent pamięci hosta" i "Łączna liczba Połączenie ions", aby otrzymywać powiadomienia, jeśli system przekroczy którykolwiek z określonych progów.

  • Użyj Szczegółowe informacje wydajności zapytań lub skoroszytów platformy Azure, aby zidentyfikować wszelkie problematyczne lub powoli uruchomione zapytania, a następnie je zoptymalizować.

  • W przypadku serwerów produkcyjnych baz danych zbierz diagnostykę w regularnych odstępach czasu, aby upewnić się, że wszystko działa bezproblemowo. Jeśli nie, rozwiąż wszelkie zidentyfikowane problemy i rozwiąż je.

Następne kroki

Aby znaleźć odpowiedzi na najważniejsze pytania lub opublikować lub odpowiedzieć na pytanie, odwiedź witrynę Stack Overflow.