Condividi tramite


Risolvere i problemi di prestazioni delle query nel server flessibile di Database di Azure per MySQL

SI APPLICA A:Database di Azure per MySQL - Server singolo Database di Azure per MySQL - Server flessibile

Importante

Il server singolo del Database di Azure per MySQL è in fase di ritiro. È consigliabile eseguire l'aggiornamento al server flessibile del Database di Azure per MySQL. Per altre informazioni sulla migrazione a Database di Azure per MySQL - Server flessibile, vedere Cosa succede a Database di Azure per MySQL - Server singolo?

Le prestazioni delle query possono essere influenzate da più fattori, quindi è prima importante esaminare l'ambito dei sintomi riscontrati nell'istanza del server flessibile Database di Azure per MySQL. Ad esempio, le prestazioni delle query sono lente per:

  • Tutte le query in esecuzione nell'istanza del server flessibile Database di Azure per MySQL?
  • Un set di query specifico?
  • Una query specifica?

Tenere inoltre presente che eventuali modifiche recenti alla struttura o ai dati sottostanti delle tabelle su cui si sta eseguendo la query possono influire sulle prestazioni.

Abilitazione della funzionalità di registrazione

Prima di analizzare le singole query, è necessario definire i relativi benchmark. Con queste informazioni, è possibile implementare la funzionalità di registrazione nel server di database per tracciare le query che superano una soglia specificata in base alle esigenze dell'applicazione.

Database di Azure per MySQL server flessibile, è consigliabile usare la funzionalità di log delle query lente per identificare le query che richiedono più tempo di N secondi da eseguire. Dopo aver identificato le query dal log delle query con esecuzione lenta, è possibile usare la diagnostica MySQL per risolvere i problemi di queste query.

Prima di iniziare a tracciare query con esecuzione prolungata, è necessario abilitare il parametro slow_query_log usando il portale di Azure o l'interfaccia della riga di comando di Azure. Con questo parametro abilitato, è anche necessario configurare il valore del parametro long_query_time per specificare il numero di secondi durante i quali le query possono essere eseguite prima di essere identificate come query "con esecuzione lenta". Il valore predefinito del parametro è 10 secondi, ma è possibile modificarlo per soddisfare le esigenze del contratto di servizio dell'applicazione.

Database di Azure per MySQL'interfaccia del log delle query lente del server flessibile.

Nonostante il log delle query lente sia uno strumento ideale per tracciare query con esecuzione prolungata, esistono alcuni scenari in cui potrebbe non essere efficace. Ad esempio, il log delle query lente può:

  • influire negativamente sulle prestazioni se il numero di query è molto elevato o se l'istruzione di esecuzione della query è molto grande. Modificare il valore del parametro long_query_time di conseguenza.
  • Potrebbe non essere utile se è stato abilitato anche il parametro log_queries_not_using_index, che specifica di registrare le query previste per recuperare tutte le righe. Le query che eseguono un'analisi completa dell'indice sfruttano un indice ma vengono registrate perché questo non limita il numero di righe restituite.

Recupero delle informazioni dai log

I log sono disponibili per un massimo di sette giorni dalla data di creazione. È possibile elencare e scaricare i log di query lente usando il portale o l'interfaccia della riga di comando di Azure. Nel portale di Azure passare al server, in Monitoraggio, selezionare Log del servere poi selezionare la freccia verso il basso accanto a una voce per scaricare i log associati alla data e all'ora in cui si sta effettuando l’analisi.

Database di Azure per MySQL server flessibile che recupera i dati dai log.

Inoltre, se i log delle query lente sono integrati con i log di Monitoraggio di Azure tramite i log di diagnostica, è possibile eseguire le query in un editor per analizzarle ulteriormente:

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

Nota

Per ottenere altri esempi su come iniziare a diagnosticare i log delle query lente tramite i log di Diagnostica, vedere Analizzare i log nei log di Monitoraggio di Azure.

Lo snapshot seguente illustra una query lenta di esempio.

# 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%';;

Si noti che la query è stata eseguita in 26 secondi, esaminata per oltre 443.000 righe e ha restituito 126 righe di risultati.

In genere, è consigliabile concentrarsi sulle query con valori elevati per Query_time e Rows_examined. Tuttavia, se si notano query con un Query_time elevato ma soltanto pochi Rows_examined, questo spesso indica la presenza di un rallentamento della risorsa. In questi casi, è consigliabile verificare i rallentamenti sono nell’IO o nell’utilizzo della CPU.

Profilatura di una query

Dopo aver identificato una query con esecuzione lenta specifica, è possibile usare il comando EXPLAIN e la profilatura per acquisire ulteriori dettagli.

Per controllare il piano di query, eseguire il comando seguente:

EXPLAIN <QUERY>

Nota

Per altre informazioni sull'uso delle istruzioni EXPLAIN, vedere Come usare EXPLAIN per profilare le prestazioni delle query in Database di Azure per MySQL server flessibile.

Oltre a creare un piano EXPLAIN per una query, è possibile usare il comando SHOW PROFILE, che consente di diagnosticare l'esecuzione di istruzioni eseguite all'interno della sessione corrente.

Per abilitare la profilatura e profilare una query specifica in una sessione, eseguire il set di comandi seguente:

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

Nota

La profilatura di singole query è disponibile solo in una sessione e le istruzioni cronologiche non possono essere profilate.

Esaminiamo nel dettaglio l'uso di questi comandi per profilare una query. Prima di tutto, abilitare la profilatura per la sessione corrente eseguendo il comando SET PROFILING = 1:

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

Eseguire quindi una query subottimale che esegue una scansione completa della tabella:

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)

Poi visualizzare un elenco di tutti i profili di query disponibili eseguendo il comando SHOW PROFILES:

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)

Infine, per visualizzare il profilo della query 1, eseguire il comando SHOW PROFILE FOR QUERY 1.

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)

Elenco delle query più usate nel server del database

Ogni volta che si esegue la risoluzione dei problemi relativi alle prestazioni delle query, è utile comprendere quali query vengono eseguite più spesso nell'istanza del server flessibile Database di Azure per MySQL. È possibile usare queste informazioni per rilevare se una delle query principali richiede più tempo del solito per l'esecuzione. Inoltre, uno sviluppatore o un amministratore di database potrebbe usare queste informazioni per rilevare se una query presenta un aumento improvviso del numero di esecuzioni e della durata.

Per elencare le prime 10 query eseguite sull'istanza del server flessibile Database di Azure per MySQL, eseguire la query seguente:

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;

Nota

usare questa query per ottenere il benchmark delle query eseguite più in alto nel server del database e determinare se è stata apportata una modifica nelle query principali o se la durata dell’esecuzione delle query esistenti nel benchmark è aumentata.

Elencare le 10 query più rilevanti in termini di tempo di esecuzione totale

L'output della query seguente fornisce informazioni sulle prime 10 query in esecuzione sul server del database e sul numero di esecuzioni nel server del database. Fornisce anche altre informazioni utili, come ad esempio latenze delle query, periodi di blocco, numero di tabelle temporanee create nel contesto del runtime delle query e così via. Usare l’output della query per tenere traccia delle query principali nel database e delle modifiche apportate a fattori come le latenze, che potrebbero indicare la possibilità di ritoccare la query per evitare eventuali rischi futuri.

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;

Monitoraggio del Garbage Collection InnoDB

Quando il Garbage Collection InnoDB è bloccato o rallentato, il database può sviluppare un notevole ritardo di eliminazione, che può influire negativamente sull'utilizzo dell'archiviazione e sulle prestazioni delle query.

La lunghezza dell'elenco della cronologia dei segmenti di rollback di InnoDB misura il numero di record delle modifiche (HLL) archiviati nel registro degli annullamenti. Un valore HLL crescente indica che i thread di Garbage Collection di InnoDB (thread di eliminazione) non sono in linea con il carico di lavoro in scrittura o che l'eliminazione viene bloccata da una query o da una transazione con esecuzione prolungata.

Un numero eccessivo di ritardi nell'operazione di Garbage Collection può avere conseguenze gravi e negative:

  • Lo spazio della tabella del sistema InnoDB si espande, accelerando così la crescita del volume di archiviazione sottostante. A volte, lo spazio delle tabelle di sistema può aumentare di diversi terabyte in seguito a un'eliminazione bloccata.
  • I record contrassegnati dall'eliminazione non verranno rimossi in modo tempestivo. Ciò può causare l'aumento degli spazi delle tabelle InnoDB e impedire al motore di riutilizzare lo spazio di archiviazione occupato da tali record.
  • Le prestazioni di tutte le query potrebbero peggiorare e l'utilizzo della CPU potrebbe aumentare a causa della crescita delle strutture di archiviazione InnoDB.

Di conseguenza, è importante monitorare valori, modelli e tendenze HLL.

Ricerca dei valori HLL

È possibile trovare il valore HLL eseguendo il comando "Mostra stato mototre InnoDB". Il valore verrà elencato nell'output, sotto l'intestazione TRANSACTIONS:

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 
 
(...) 

È anche possibile determinare il valore HLL eseguendo una query sulla tabella 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)

Interpretazione dei valori HLL

Quando si interpretano i valori HLL, prendere in considerazione le linee guida elencate nella tabella seguente:

valore Note
Minore di 10.000 Valori normali che indicano che Garbage Collection non è in ritardo.
Tra 10.000 e 1.000.000 Questi valori indicano un ritardo secondario in Garbage Collection. Tali valori potrebbero essere accettabili se rimangono stabili e non aumentano.
Maggiore di 1.000.000 Questi valori devono essere esaminati e potrebbero richiedere correzioni

Indirizzamento di valori HLL eccessivi

Se HLL mostra picchi di grandi dimensioni o presenta un modello di crescita periodica, esaminare immediatamente le query e le transazioni in esecuzione nell'istanza del server flessibile Database di Azure per MySQL. È quindi possibile risolvere eventuali problemi del carico di lavoro che potrebbero impedire lo stato di avanzamento del processo di Garbage Collection. Benché non sia previsto che il database sia privo di ritardo di eliminazione, il ritardo non deve essere lasciato aumentare in modo incontrollato.

Per ottenere informazioni sulle transazioni dalla tabella information_schema.innodb_trx, ad esempio, eseguire i comandi seguenti:

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

I dettagli nella colonna trx_started consentono di calcolare l'età delle transazioni.

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%';
(…) 

Per informazioni sulle sessioni di database correnti, incluso il tempo trascorso nello stato corrente della sessione, controllare la tabella information_schema.processlist. L'output seguente, ad esempio, mostra una sessione che esegue attivamente una query per gli ultimi 1462 secondi:

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%';
 
(...) 

Consigli

  • Accertarsi che il database disponga di risorse sufficienti ad eseguire le query. A volte potrebbe essere necessario aumentare le dimensioni dell'istanza per ottenere più core della CPU e memoria aggiuntiva per supportare il carico di lavoro.

  • Evitare transazioni di grandi dimensioni o con esecuzione prolungata suddividendole in transazioni più piccole.

  • Configurare innodb_purge_threads in base al carico di lavoro per migliorare l'efficienza per le operazioni di eliminazione in background.

    Nota

    Testare le modifiche apportate a questa variabile server per ciascun ambiente per misurare la variazione del comportamento del motore.

  • Usare gli avvisi in "Percentuale CPU host" e "Connessioni totali" in modo da ricevere notifiche se il sistema supera una delle soglie specificate.

  • Usare informazioni dettagliate sulle prestazioni delle query o cartelle di lavoro di Azure per identificare eventuali query problematiche o con esecuzione lenta e quindi ottimizzarle.

  • Per i server di database di produzione, acquisire la diagnostica a intervalli regolari per garantire che tutto funzioni correttamente. In caso contrario, risolvere eventuali problemi identificati.

Passaggi successivi

Per trovare risposte di peer alle domande più importanti o per pubblicare o rispondere a una domanda, visitare Stack Overflow.