MySQL crea tabelle temporanee su disco. Come posso fermarlo?


27

Stiamo gestendo un sito (Moodle) che gli utenti attualmente trovano lento. Penso di aver rintracciato il problema su MySQL creando tabelle temporanee su disco. Osservo la variabile created_tmp_disk_tablesnell'amministrazione del server Mysql Workbench e il numero aumenta con circa 50 tabelle / s. Dopo un giorno di utilizzo, created_tmp_disk_tablesè> 100k. Inoltre, la memoria non sembra essere stata rilasciata. L'utilizzo continua ad aumentare fino a quando il sistema diventa praticamente inutilizzabile e dobbiamo riavviare MySQL. Ho bisogno di riavviarlo quasi ogni giorno e inizia con l'utilizzo di circa il 30-35% di memoria disponibile e terminando la giornata con l'80%.

Non ho BLOB nel database né controllo sulle query, quindi non posso tentare di ottimizzarle. Ho anche usato la procedura guidata di configurazione di Percona per generare un file di configurazione ma che my.ini non ha risolto il mio problema.

Domande

  1. Cosa devo modificare per impedire a MySQL di creare tabelle temporanee su disco? Ci sono impostazioni che devo modificare? Devo buttargli più memoria?

  2. Come posso impedire a MySQL di consumare la mia memoria?

modificare

Ho abilitato il slow_queriesregistro e ho scoperto che la query SELECT GET_LOCK()era registrata come lenta. Una rapida ricerca ha rivelato che avevo consentito connessioni persistenti nella configurazione di PHP ( mysqli.allow_persistent = ON). L'ho spento. Ciò ha ridotto la velocità con cui MySQL consuma memoria, ma sta comunque creando tabelle temporanee.

Ho anche verificato che key_buffer sizesia abbastanza grande. Ho guardato la variabile key_writes. Questo dovrebbe essere zero. In caso contrario, aumentare il key_buffer_size. Ho zero key_readse zero, key_writesquindi presumo che key_buffer_sizesia abbastanza grande.

Ho aumentato i tmp_table_sizee max-heap-table-sizea 1024M poiché un aumento di Created_tmp_disk_tables potrebbe indicare che le tabelle non possono essere contenute nella memoria. Questo non l'ha risolto.

Rif: http://www.mysqlperformanceblog.com/2007/08/16/how-much-overhead-is-caused-by-on-disk-temporary-tables/

Modifica 2

Se ne vedi molti sort_merge_passesal secondo nell'output SHOW GLOBAL STATUS, puoi considerare di aumentare il sort_buffer_sizevalore. Ne avevo 2 sort_merge_passesin un'ora, quindi ritengo sort_buffer_sizeche sia abbastanza grande.

Rif: Mysql Manual on sort_buffer_size

Modifica 3

Ho modificato l'ordinamento e l'aggiunta dei buffer come suggerito da @RolandoMySQLDBA. Il risultato è visualizzato nella tabella qui sotto ma penso che created_tmp_tables_on_disksia ancora alto. Ho riavviato il server mysql dopo aver modificato il valore e verificato il created_tmp_tables_on_diskdopo un giorno (8h) e calcolato la media. Altri suggerimenti? Mi sembra che ci sia qualcosa che non rientra in una sorta di contenitore ma non riesco a capire di cosa si tratti.

+---------------------+-------------+-------------+--------------------+
| Tmp_table_size,     | Sort_buffer | Join_buffer | No of created      |
| max_heap_table_size |             |             | tmp_tables on disk |
+---------------------+-------------+-------------+--------------------+
| 125M                | 256K        | 256K        |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 512K        | 512K        |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 1M          | 1M          |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 4M          | 4M          |  100k/h            |
+---------------------+-------------+-------------+--------------------+   



Questa è la mia configurazione:

+-----------------------+-----------------------+
|DATABASE SERVER        |WEB SERVER             |
+-----------------------+-----------------------+
|Windows Server 2008 R2 |Windows Server 2008 R2 |
+-----------------------+-----------------------+
|MySQL 5.1.48           |IIS 7.5                |
+-----------------------+-----------------------+
|4 Core CPU             |4 Core CPU             |
+-----------------------+-----------------------+
|4GB RAM                |8GB RAM                |
+-----------------------+-----------------------+

Informazioni aggiuntive

+--------------------+---------+
|PARAM               |VALUE    |
+--------------------+---------+
|Num of tables in Db |361      |
+--------------------+---------+
|Size of database    |2.5G     |
+--------------------+---------+
|Database engine     |InnoDB   |
+--------------------+---------+
|Read/write ratio    |3.5      |
|(Innodb_data_read/  |         |
|innodb_data_written)|         |
+--------------------+---------+
|Avg table size      |15k rows |
+--------------------+---------+
|Max table size      |744k rows|
+--------------------+---------+

Questa configurazione mi è stata fornita, quindi ho un controllo limitato su di essa. Il web server utilizza pochissima CPU e RAM, quindi ho escluso quella macchina come un collo di bottiglia. La maggior parte delle impostazioni di MySQL proviene da uno strumento di generazione automatica di configurazione.

Ho monitorato il sistema usando PerfMon per alcuni giorni rappresentativi. Da ciò, concludo che non è il sistema operativo che sta scambiando su disco.

My.ini

[client]
port=3306
[mysql]
default-character-set=utf8

[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.1/"
datadir="D:/DBs/Data/"
default-character-set=utf8
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=125
query_cache_size=350M
table_cache=1520
tmp_table_size=125M
table-definition-cache= 1024
max-heap-table-size= 32M
thread_cache_size=38

MyISAM Specific options
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=125M
key_buffer_size=55M
read_buffer_size=1024K
read_rnd_buffer_size=256K
sort_buffer_size=1024K
join_buffer_size=1024K


INNODB Specific options
innodb_data_home_dir="D:/DBs/"
innodb_additional_mem_pool_size=32M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=16M
innodb_buffer_pool_size=2G
innodb_log_file_size=407M
innodb_thread_concurrency=8

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White dice GoFundMonica

Risposte:


16

Guardando my.ini, ho due suggerimenti

SUGGERIMENTO N. 1

Vorrei ripristinare le seguenti impostazioni nel tuo my.ini

sort_buffer_size=4M
join_buffer_size=4M

In questo modo alcuni join e gli ordinamenti rimarranno nella memoria. Ovviamente, una volta che uno JOINo ORDER BYpiù ha bisogno di più 4M, passerà alla pagina su disco come una tabella MyISAM.

Se non riesci ad accedere come root@localhost, quindi riavvia mysql con

C:\> net stop mysql
C:\> net start mysql

Se riesci ad accedere come root @ localhost, non devi riavviare mysql per usare queste impostazioni.

Basta eseguirlo nel client MySQL:

SET @FourMegs = 1024 * 1024 * 4;
SET GLOBAL sort_buffer_size = @FourMegs;
SET GLOBAL join_buffer_size = @FourMegs;

SUGGERIMENTO # 2

Poiché i tuoi dati sono su Drive D:, potresti avere I / O su disco su Drive C:.

Si prega di eseguire questa query:

mysql> show variables like 'tmpdir';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tmpdir        | C:\Windows\TEMP |
+---------------+-----------------+
1 row in set (0.00 sec)

Da quando eseguo mysql sul mio desktop con le impostazioni predefinite, le mie tabelle temporanee vengono scritte su Drive C:. Se l'unità D è un disco migliore di unità C:, forse si può mappare tabelle temporanee di guidare, D:impostando tmpdir nel my.inimodo seguente:

tmpdir="D:/DBs/"

Dovrai riavviare mysql poiché tmpdir non è una variabile dinamica.

Provaci !!!

AGGIORNAMENTO 2013-11-29 10:09 EST

SUGGERIMENTO # 3

Dato che MySQL è in esecuzione in Windows e non è possibile toccare le query nel pacchetto principale, ho due idee che devono essere fatte insieme.

IDEA n. 1: sposta il database su una macchina Linux

Dovresti essere capace di

  • Installa una macchina Linux
  • Installa MySQL sul computer Linux
  • Abilita registrazione binaria per MySQL in Windows
  • mysqldump il database in un file SQL di testo
  • Carica il file SQL su MySQL in esecuzione su Linux
  • Replica dell'installazione da MySQL / Windows a MySQL / Linux

IDEA n. 2: riconfigurare Moodle in modo che punti alla macchina Linux

Moodle è stato progettato per LAMP in primo luogo. Basta modificare i file di configurazione in modo che puntino alla macchina Linux anziché a localhost.

Ecco un link a un vecchio documento di Moodle 2.3 sulla configurazione di MySQL: http://docs.moodle.org/23/en/Installing_Moodle#Create_an_empty_database

Sono sicuro che sono disponibili anche gli ultimi documenti.

Qual è il punto di spostare il database su Linux ???

In che modo aiuta la situazione della tabella temporanea ???

Vorrei quindi suggerire di impostare un disco RAM come cartella di destinazione per le tabelle temporanee

La creazione della tabella temporanea continuerà, ma verrà scritta nella RAM anziché nel disco. riduzione dell'I / O del disco.

AGGIORNAMENTO 2013-11-29 11:24 EST

SUGGERIMENTO # 4

Suggerirei di rivisitare SUGGESTION # 2 con un disco RAID-0 veloce (32+ GB), configurandolo come Drive T: (T per Temp). Dopo aver installato un tale disco, aggiungere questo a my.ini:

[mysqld]
tmpdir="T:\"

Il riavvio di MySQL sarebbe richiesto, usando

net stop mysql
net start mysql

A proposito ho detto RAID-0 di proposito in modo da poter ottenere buone prestazioni di scrittura su un RAID-1, RAID-10. Un disco di tabella tmp non è qualcosa che renderei ridondante.

Senza ottimizzare le query come @RaymondNijland ha commentato, non è possibile ridurre in alcun modo il conteggio della creazione della tabella temporanea. SUGGESTION #3e SUGGESTION #4offrire l'accelerazione della creazione della tabella temporanea e dell'I / O della tabella temporanea come unica alternativa.


13

Rispondo alla mia domanda qui per completezza

Selezionerò @RolandoMySQLDBA come risposta preferita perché mi ha dato il maggior numero di suggerimenti anche se in realtà non ha risolto il mio problema.

Di seguito sono riportati i risultati della mia indagine

Conclusione

MySQL su Windows crea solo molte tabelle temporanee e l'ottimizzazione di MySQL modificando il contenuto dei file di configurazione non ha aiutato.

Dettagli

La tabella mostra i parametri che ho modificato rispettivamente in my.ini prima di eseguire qualsiasi query. MySQL è stato riavviato tra ogni test.

Ho usato my.ini trovato nella domanda originale come modello e poi ho cambiato il valore dei parametri uno per uno secondo la tabella seguente.

Ho usato JMeter per generare 100 richieste web simultanee (poiché ciò rappresentava il nostro utilizzo) ripetute 10 dieci volte. Ciascuno Testconsisteva quindi di 1000 richieste in totale. Ciò ha comportato successive chiamate al database. Ciò ha dimostrato che MySQL avrebbe creato molte tabelle temporanee indipendentemente dai parametri di configurazione che abbiamo modificato.

+----+------------+-------+---------------+------------+
|Test|Parameter   |Value  |NumOfTempTables|Db Max Conn |
+----+------------+-------+---------------+------------+
| 1  |key_buffer_ | 25M   | 30682         | 29         |
|    |size        |       |               |            | 
+----+------------+-------+---------------+------------+
| 2  |key_buffer_ | 55M   | 30793         | 29         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 3  |key_buffer_ | 100M  | 30666         | 28         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 4  |key_buffer_ | 125M  | 30593         | 24         |
|    |size        |       |               |            | 
+----+------------+-------+---------------+------------+
| 5  |query_cache_| 100M  | 30627         | 32         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 6  |query_cache_| 250M  | 30761         | 26         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 7  |query_cache_| 500M  | 30864         | 83*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 8  |query_cache_| 1G    | 30706         | 75*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 9  |tmp_table_  | 125M  | 30724         | 31         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 10 |tmp_table_  | 250M  | 30689         | 90*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 11 |tmp_table_  | 500M  | 30792         | 28         |
|    |size        |       |               |            |  
+----+------------+-------+---------------+------------+
| 12 |Sort_buffer&| 256K  | 30754         | 28         |
|    |Join_buffer |       |               |            |
+----+------------+-------+---------------+------------+
| 13 |Sort_buffer&| 512K  | 30788         | 30         |
|    |Join_buffer |       |               |            | 
+----+------------+-------+---------------+------------+
| 14 |Sort_buffer&| 1M    | 30788         | 28         |
|    |Join_buffer |       |               |            | 
+----+------------+-------+---------------+------------+
| 15 |Sort_buffer&| 4M    | 30642         | 35         |
|    |Join_buffer |       |               |            |
+----+------------+-------+---------------+------------+
| 16 |innodb-     | 1G    | 30695         | 33         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            |
+----+------------+-------+---------------+------------+
| 17 |innodb-     | 2G    | 30791         | 28         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            | 
+----+------------+-------+---------------+------------+
| 18 |innodb-     | 3G    | 30719         | 34         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            |  
+----+------------+-------+---------------+------------+

* Media di tre corse

Le immagini seguenti mostrano la quantità di memoria e CPU richiesta dal server di database per le diverse configurazioni. Le linee nere indicano i valori minimo e massimo e le barre blu indicano i valori iniziale e finale. La memoria massima era 4096Mcome indicato nella domanda.

Utilizzo della memoria Uso della CPU


Quale motore di archiviazione stai utilizzando? MyiSAM? Se non si utilizzano le tabelle MyISAM, non è significativo fare affidamento su key_buffer_size. se stai utilizzando il motore di archiviazione innodb, qual è la dimensione di innodb_buffer_pool_size. Stai usando query_cache?
Kasi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.