MySQL membuat tabel sementara pada disk. Bagaimana saya menghentikannya?

27

Kami menjalankan situs (Moodle) yang saat ini ditemukan lambat oleh pengguna. Saya pikir saya telah melacak masalah ke MySQL membuat tabel sementara pada disk. Saya menonton variabel created_tmp_disk_tablesdalam administrasi server Mysql Workbench dan jumlahnya meningkat sekitar 50 tabel / s. Setelah penggunaan sehari, created_tmp_disk_tablesadalah> 100rb. Selain itu, memori sepertinya tidak akan dirilis. Penggunaan terus meningkat hingga sistem menjadi cukup banyak tidak dapat digunakan dan kita harus memulai kembali MySQL. Saya harus memulai kembali hampir setiap hari dan itu dimulai dengan menggunakan sekitar 30-35% memori yang tersedia dan menyelesaikan hari dengan 80%.

Saya tidak memiliki gumpalan dalam database dan tidak memiliki kontrol atas permintaan sehingga saya tidak dapat mencoba untuk mengoptimalkannya. Saya juga telah menggunakan Wisaya Confirguration Wizard untuk menghasilkan file konfigurasi tetapi my.ini juga tidak menyelesaikan masalah saya.

Pertanyaan

  1. Apa yang harus saya ubah untuk menghentikan MySQL dari membuat tabel sementara pada disk? Apakah ada pengaturan yang perlu saya ubah? Haruskah saya membuang lebih banyak memori padanya?

  2. Bagaimana saya bisa menghentikan MySQL dari memakan memori saya?

Edit

Saya mengaktifkan slow_querieslog dan menemukan bahwa kueri SELECT GET_LOCK()dicatat sebagai lambat. Pencarian cepat mengungkapkan bahwa saya telah mengizinkan koneksi persisten dalam konfigurasi PHP ( mysqli.allow_persistent = ON). Saya mematikan ini. Ini mengurangi tingkat di mana MySQL mengkonsumsi memori. Ini masih membuat tabel sementara.

Saya juga memeriksa key_buffer sizeapakah ukurannya cukup besar. Saya melihat variabelnya key_writes. Ini harus nol. Jika tidak, tambah. key_buffer_sizeSaya punya nol key_readsdan nol key_writesjadi saya berasumsi bahwa key_buffer_sizeitu cukup besar.

Saya meningkatkan tmp_table_sizedan max-heap-table-sizemenjadi 1024M karena peningkatan Created_tmp_disk_tables dapat mengindikasikan bahwa tabel tidak dapat masuk dalam memori. Ini tidak menyelesaikannya.

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

Edit 2

Jika Anda melihat banyak sort_merge_passesper detik di SHOW GLOBAL STATUS output, Anda dapat mempertimbangkan untuk meningkatkan sort_buffer_sizenilainya. Saya punya 2 sort_merge_passesdalam satu jam jadi saya anggap sort_buffer_sizecukup besar.

Ref: Manual Mysql aktif sort_buffer_size

Edit 3

Saya telah memodifikasi pengurutan dan bergabung dengan buffer seperti yang disarankan oleh @Rando_MySQLDBA. Hasilnya ditampilkan dalam tabel di bawah ini tetapi saya pikir created_tmp_tables_on_diskmasih tinggi. Saya me-restart server mysql setelah saya mengubah nilainya dan memeriksa created_tmp_tables_on_disksetelah sehari (8 jam) dan menghitung rata-rata. Ada saran lain? Sepertinya saya ada sesuatu yang tidak muat di dalam semacam wadah tapi saya tidak tahu apa itu.

+---------------------+-------------+-------------+--------------------+
| 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            |
+---------------------+-------------+-------------+--------------------+   



Ini adalah konfigurasi saya:

+-----------------------+-----------------------+
|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                |
+-----------------------+-----------------------+

Informasi tambahan

+--------------------+---------+
|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|
+--------------------+---------+

Pengaturan ini diberikan kepada saya sehingga saya memiliki kontrol terbatas atasnya. Server web menggunakan sangat sedikit CPU dan RAM jadi saya telah mengecualikan mesin itu sebagai hambatan. Mayoritas pengaturan MySQL berasal dari alat pembuatan-otomatis konfigurasi.

Saya telah memonitor sistem menggunakan PerfMon selama beberapa hari yang representatif. Dari itu, saya menyimpulkan bahwa bukan OS yang bertukar ke disk.

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
pengguna30431
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Paul White mengatakan GoFundMonica

Jawaban:

16

Melihat itu my.ini, saya punya dua saran

SARAN # 1

Saya akan menambahkan pengaturan berikut di komputer Anda my.ini

sort_buffer_size=4M
join_buffer_size=4M

Ini akan membuat beberapa bergabung dan mengurutkan tinggal di memori. Tentu saja, sekali JOINatau ORDER BYlebih dari kebutuhan 4M, itu akan halaman ke disk sebagai tabel MyISAM.

Jika Anda tidak dapat masuk sebagai root@localhost, kemudian mulai kembali mysql dengan

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

Jika Anda dapat masuk sebagai root @ localhost, Anda tidak perlu me-restart mysql untuk menggunakan pengaturan ini.

Jalankan saja ini di klien MySQL:

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

SARAN # 2

Karena Data Anda di Drive D:, Anda mungkin memiliki Disk I / O di Drive C:.

Silakan jalankan kueri ini:

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

Karena saya menjalankan mysql di Desktop saya dengan default, tabel temp saya sedang ditulis ke Drive C:. Jika Drive D adalah disk lebih baik dari drive C:, mungkin Anda dapat memetakan tabel temp untuk drive D:dengan menetapkan tmpdir di my.inisebagai berikut:

tmpdir="D:/DBs/"

Anda harus me-restart mysql karena tmpdir bukan variabel dinamis.

Cobalah !!!

UPDATE 2013-11-29 10:09 EST

SARAN # 3

Mengingat fakta bahwa MySQL berjalan di Windows dan Anda tidak dapat menyentuh pertanyaan dalam paket inti, saya punya dua ide yang harus dilakukan bersama.

IDEA # 1: Pindahkan Database ke Mesin Linux

kamu harus bisa

  • Siapkan mesin Linux
  • Instal MySQL di mesin Linux
  • Aktifkan Binary Logging untuk MySQL di Windows
  • mysqldump database ke file SQL teks
  • Memuat file SQL ke MySQL yang berjalan di Linux
  • Setup replikasi dari MySQL / Windows ke MySQL / Linux

IDEA # 2: Konfigurasi ulang Moodle untuk menunjuk ke Mesin Linux

Moodle dirancang untuk LAMP di tempat pertama. Cukup ganti file config untuk menunjuk ke mesin Linux alih-alih localhost.

Berikut ini tautan ke dokumen Moodle 2.3 lama tentang pengaturan MySQL: http://docs.moodle.org/23/en/Installing_Moodle#Create_an_empty_database

Saya yakin dokumen terbaru juga tersedia.

Apa gunanya Memindahkan Database ke Linux ???

Bagaimana ini membantu situasi tabel temporer ???

Saya kemudian akan menyarankan menyiapkan disk RAM sebagai folder target untuk tabel temp Anda

Pembuatan tabel temp masih akan terjadi, tetapi akan ditulis ke RAM daripada disk. mengurangi Disk I / O.

UPDATE 2013-11-29 11:24 EST

SARAN # 4

Saya akan menyarankan mengunjungi kembali SARAN # 2 dengan disk RAID-0 yang cepat (32+ GB), mengkonfigurasinya sebagai Drive T: (T for Temp). Setelah menginstal disk seperti itu, tambahkan ini ke my.ini:

[mysqld]
tmpdir="T:\"

Restart MySQL akan diperlukan, menggunakan

net stop mysql
net start mysql

BTW I sengaja mengatakan RAID-0 sehingga Anda bisa mendapatkan kinerja penulisan yang baik melalui RAID-1, RAID-10. Disk tabel tmp bukanlah sesuatu yang saya buat berlebihan.

Tanpa mengoptimalkan kueri seperti yang dikomentari @RaymondNijland, Anda tidak dapat mengurangi jumlah pembuatan tabel temp dengan cara apa pun. SUGGESTION #3dan SUGGESTION #4menawarkan mempercepat pembuatan temp table dan temp table I / O sebagai satu-satunya alternatif.

RolandoMySQLDBA
sumber
13

Saya menjawab pertanyaan saya sendiri di sini untuk kelengkapan

Saya akan memilih @RolandoMySQLDBA sebagai jawaban yang disukai karena itu memberi saya petunjuk yang paling meskipun tidak benar-benar menyelesaikan masalah saya.

Di bawah ini adalah hasil penyelidikan saya

Kesimpulan

MySQL di Windows hanya membuat banyak tabel sementara dan menyetel MySQL dengan memodifikasi konten file konfigurasi tidak membantu.

Detail

Tabel merinci parameter yang telah saya modifikasi di my.ini masing-masing sebelum menjalankan kueri. MySQL dimulai kembali di antara setiap pengujian.

Saya menggunakan my.ini yang ditemukan dalam pertanyaan asli sebagai templat dan saya kemudian mengubah nilai parameter satu per satu sesuai dengan tabel di bawah ini.

Saya menggunakan JMeter untuk menghasilkan 100 permintaan web bersamaan (seperti yang mewakili penggunaan kami) diulang 10 sepuluh kali. Masing-masing Testterdiri dari 1000 permintaan secara total. Ini menghasilkan panggilan basis data selanjutnya. Ini menunjukkan bahwa MySQL akan membuat banyak tabel sementara terlepas dari parameter konfigurasi apa yang kami ubah.

+----+------------+-------+---------------+------------+
|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   |       |               |            |  
+----+------------+-------+---------------+------------+

* Rata-rata tiga berjalan

Gambar di bawah ini menggambarkan jumlah memori dan CPU yang dibutuhkan oleh server database untuk konfigurasi yang berbeda. Garis hitam menunjukkan nilai minimum dan maksimum dan bilah biru menunjukkan nilai awal dan akhir. Memori maksimum 4096Mseperti yang ditunjukkan dalam pertanyaan.

Penggunaan Memori Penggunaan CPU

pengguna30431
sumber
Mesin penyimpanan mana yang Anda gunakan? MyiSAM? Jika Anda tidak menggunakan tabel MyISAM, tidak berarti mengandalkan key_buffer_size. jika Anda menggunakan mesin penyimpanan innodb, berapa ukuran innodb_buffer_pool_size. Apakah Anda menggunakan query_cache?
kasi