MySQL สร้างตารางชั่วคราวบนดิสก์ ฉันจะหยุดมันได้อย่างไร


27

เรากำลังเรียกใช้ไซต์ (Moodle) ที่ผู้ใช้พบว่าช้า ฉันคิดว่าฉันได้ติดตามปัญหาของ MySQL ที่สร้างตารางชั่วคราวบนดิสก์ ฉันดูตัวแปรcreated_tmp_disk_tablesในการดูแลเซิร์ฟเวอร์ Mysql Workbench และจำนวนเพิ่มขึ้นด้วยประมาณ 50 tables / s หลังจากใช้ไป 1 วันcreated_tmp_disk_tablesคือ> 100k นอกจากนี้ดูเหมือนว่าหน่วยความจำจะไม่ออก การใช้งานเพิ่มขึ้นเรื่อย ๆ จนกระทั่งระบบใช้งานไม่ได้และเราต้องเริ่ม MySQL ใหม่ ฉันต้องเริ่มต้นใหม่เกือบทุกวันและเริ่มต้นด้วยการใช้หน่วยความจำที่มีอยู่ประมาณ 30-35% และจบวันด้วย 80%

ฉันไม่มี blobs ในฐานข้อมูลและไม่สามารถควบคุมการค้นหาได้ดังนั้นฉันจึงไม่สามารถพยายามปรับให้เหมาะสม ฉันได้ใช้Percona Confirguration Wizardเพื่อสร้างไฟล์การกำหนดค่า แต่ my.ini ไม่ได้แก้ปัญหาเช่นกัน

คำถาม

  1. ฉันควรเปลี่ยนอะไรเพื่อหยุด MySQL ไม่ให้สร้างตารางชั่วคราวบนดิสก์ จำเป็นต้องเปลี่ยนการตั้งค่าหรือไม่? ฉันควรจะโยนความทรงจำมากกว่านี้หรือไม่

  2. ฉันจะหยุด MySQL ไม่ให้กินหน่วยความจำได้อย่างไร

แก้ไข

ฉันเปิดใช้งานการslow_queriesบันทึกและค้นพบว่าการสืบค้นSELECT GET_LOCK()ถูกบันทึกไว้ช้า การค้นหาอย่างรวดเร็วเปิดเผยว่าฉันอนุญาตการเชื่อมต่อแบบถาวรในการกำหนดค่า PHP ( mysqli.allow_persistent = ON) ฉันปิดสิ่งนี้แล้ว สิ่งนี้ช่วยลดอัตราการใช้งานหน่วยความจำของ MySQL ซึ่งยังคงสร้างตารางชั่วคราวอยู่

ฉันยังตรวจสอบว่าkey_buffer sizeมีขนาดใหญ่พอ key_writesผมมองไปที่ตัวแปร นี่ควรเป็นศูนย์ ถ้าไม่เพิ่มkey_buffer_size. ฉันมีศูนย์key_readsและศูนย์key_writesดังนั้นฉันคิดว่าkey_buffer_sizeมันมีขนาดใหญ่พอ

ฉันเพิ่มtmp_table_sizeและmax-heap-table-sizeถึง 1024M เนื่องจากการเพิ่มขึ้นของ created_tmp_disk_tables อาจบ่งบอกว่าตารางไม่สามารถพอดีกับหน่วยความจำได้ สิ่งนี้ไม่ได้แก้มัน

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

แก้ไข 2

หากคุณเห็นจำนวนมากsort_merge_passesต่อวินาทีในเอาต์พุต SHOW GLOBAL STATUS คุณสามารถพิจารณาเพิ่มsort_buffer_sizeมูลค่าได้ ฉันมี 2 sort_merge_passesชั่วโมงต่อชั่วโมงดังนั้นฉันคิดว่ามันsort_buffer_sizeใหญ่พอ

Ref: คู่มือ Mysql เปิด sort_buffer_size

แก้ไข 3

ฉันได้แก้ไขการเรียงลำดับและเข้าร่วมบัฟเฟอร์ตามที่แนะนำโดย @RolandoMySQLDBA ผลลัพธ์แสดงในตารางด้านล่าง แต่ฉันคิดว่าcreated_tmp_tables_on_diskยังคงสูง ฉันรีสตาร์ทเซิร์ฟเวอร์ mysql หลังจากฉันเปลี่ยนค่าและตรวจสอบcreated_tmp_tables_on_diskหลังจากผ่านไปหนึ่งวัน (8 ชั่วโมง) และคำนวณค่าเฉลี่ย ข้อเสนอแนะอื่น ๆ ? สำหรับฉันดูเหมือนว่ามีบางอย่างที่ไม่พอดีกับภาชนะบางชนิด แต่ฉันไม่สามารถคิดได้ว่ามันคืออะไร

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



นี่คือการกำหนดค่าของฉัน:

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

ข้อมูลเพิ่มเติม

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

การตั้งค่านี้มอบให้ฉันดังนั้นฉันจึงมีข้อ จำกัด ในการควบคุม เว็บเซิร์ฟเวอร์ใช้ CPU และ RAM น้อยมากดังนั้นฉันจึงแยกเครื่องดังกล่าวเป็นคอขวด การตั้งค่า MySQL ส่วนใหญ่มาจากเครื่องมือสร้างอัตโนมัติ config

ฉันได้ตรวจสอบระบบโดยใช้ PerfMon เป็นเวลาสองสามวัน จากนั้นฉันสรุปได้ว่าไม่ใช่ OS ที่เปลี่ยนเป็นดิสก์

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

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
พอลไวท์พูดว่า GoFundMonica

คำตอบ:


16

ดูที่my.iniฉันมีสองข้อเสนอแนะ

คำแนะนำ # 1

ฉันจะชนการตั้งค่าต่อไปนี้ในของคุณ my.ini

sort_buffer_size=4M
join_buffer_size=4M

สิ่งนี้จะทำให้การเข้าร่วมและการเรียงลำดับอยู่ในความทรงจำ แน่นอนเมื่อหนึ่งJOINหรือORDER BYมากกว่าความต้องการ4Mมันจะหน้าดิสก์เป็นตาราง MyISAM

หากคุณไม่สามารถเข้าสู่ระบบได้ให้root@localhostรีสตาร์ท mysql ด้วย

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

หากคุณสามารถเข้าสู่ระบบในฐานะ root @ localhost คุณไม่ต้องรีสตาร์ท mysql เพื่อใช้การตั้งค่าเหล่านี้

เรียกใช้สิ่งนี้ในไคลเอนต์ MySQL:

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

คำแนะนำ # 2

เนื่องจากข้อมูลของคุณอยู่ในไดรฟ์D:คุณอาจมี Disk I / O C:ในไดรฟ์

กรุณาเรียกใช้แบบสอบถามนี้:

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

ตั้งแต่ผมทำงาน MySQL C:บนเดสก์ท็ของฉันกับค่าเริ่มต้นของตารางชั่วคราวของฉันจะถูกเขียนไปยังไดรฟ์ หากไดรฟ์ D เป็นดิสก์ไดรฟ์ดีกว่าC:บางทีคุณสามารถ map ตารางชั่วคราวในไดรฟ์D:โดยการตั้งค่าtmpdirในmy.iniดังนี้

tmpdir="D:/DBs/"

คุณจะต้องเริ่ม mysql ใหม่เนื่องจากtmpdirไม่ใช่ตัวแปรแบบไดนามิก

ให้มันลอง !!!

อัพเดท 2013-11-29 10:09 EST

คำแนะนำ # 3

จากข้อเท็จจริงที่ว่า MySQL กำลังทำงานใน Windows และคุณไม่สามารถสัมผัสคำสั่งในแพ็คเกจหลักได้ฉันมีสองความคิดที่ทททต้องทำร่วมกัน

IDEA # 1: ย้ายฐานข้อมูลไปยังเครื่อง Linux

คุณควรจะสามารถ

  • ติดตั้งเครื่อง Linux
  • ติดตั้ง MySQL บนเครื่อง Linux
  • เปิดใช้งานการบันทึกไบนารีสำหรับ MySQL ใน Windows
  • mysqldump ฐานข้อมูลไปยังไฟล์ SQL ข้อความ
  • โหลดไฟล์ SQL ไปยัง MySQL ที่ทำงานใน Linux
  • ตั้งค่าการจำลองแบบจาก MySQL / Windows เป็น MySQL / Linux

IDEA # 2: ตั้งค่า Moodle ใหม่ให้ชี้ไปที่เครื่อง Linux

Moodle ถูกออกแบบมาเพื่อหลอดไฟตั้งแต่แรก เพียงแค่เปลี่ยนไฟล์กำหนดค่าให้ชี้ไปที่เครื่อง Linux แทน localhost

นี่คือลิงค์ไปยังเอกสารเก่าของ Moodle 2.3 ในการตั้งค่า MySQL: http://docs.moodle.org/23/th/Installing_Moodle#Create_an_empty_database

ฉันแน่ใจว่าเอกสารล่าสุดพร้อมใช้งานเช่นกัน

จุดย้ายฐานข้อมูลไปยัง Linux คืออะไร ???

สิ่งนี้จะช่วยสถานการณ์ตาราง temp ได้อย่างไร ???

ฉันจะแนะนำให้ตั้งค่าดิสก์ RAM เป็นโฟลเดอร์เป้าหมายสำหรับตารางชั่วคราวของคุณ

การสร้างตารางชั่วคราวจะยังคงเกิดขึ้น แต่มันจะถูกเขียนลงใน RAM แทนที่จะเป็นดิสก์ ลด Disk I / O

อัพเดท 2013-11-29 11:24 น

คำแนะนำ # 4

ฉันขอแนะนำให้เยี่ยมชมSUGGESTION # 2ด้วยดิสก์ RAID-0 ที่รวดเร็ว (32+ GB) โดยกำหนดเป็น Drive T: (T for Temp) หลังจากติดตั้งดิสก์ดังกล่าวให้เพิ่มสิ่งนี้ในmy.ini:

[mysqld]
tmpdir="T:\"

จำเป็นต้องมีการรีสตาร์ท MySQL โดยใช้

net stop mysql
net start mysql

BTW ฉันบอกว่า RAID-0 มีจุดประสงค์เพื่อให้คุณสามารถเขียนได้ดีกว่า RAID-1, RAID-10 ดิสก์ตาราง tmp ไม่ใช่สิ่งที่ฉันจะทำซ้ำซ้อน

หากไม่ปรับการค้นหาให้เหมาะสมเนื่องจาก @RaymondNijland แสดงความคิดเห็นอยู่คุณจะไม่สามารถลดจำนวนการสร้างตาราง temp ได้ แต่อย่างใด SUGGESTION #3และSUGGESTION #4เสนอเร่งการสร้างตารางชั่วคราวและตาราง I / O เป็นทางเลือกเดียว


13

ฉันตอบคำถามของฉันเองที่นี่เพื่อความสมบูรณ์

ฉันจะเลือก @RolandoMySQLDBA เป็นคำตอบที่ต้องการเพราะให้คำแนะนำที่ดีที่สุดถึงแม้ว่ามันจะไม่ได้แก้ปัญหาของฉัน

ด้านล่างนี้เป็นผลการสอบสวนของฉัน

ข้อสรุป

MySQL บน Windows เพิ่งสร้างตารางชั่วคราวจำนวนมากและปรับแต่ง MySQL โดยการแก้ไขเนื้อหาของไฟล์การกำหนดค่าไม่ได้ช่วยอะไร

รายละเอียด

ตารางแสดงรายละเอียดพารามิเตอร์ที่ฉันได้แก้ไขใน my.ini ตามลำดับก่อนดำเนินการแบบสอบถามใด ๆ MySQL เริ่มต้นใหม่ระหว่างการทดสอบแต่ละครั้ง

ฉันใช้ my.ini ที่พบในคำถามเดิมเป็นเทมเพลตจากนั้นฉันก็เปลี่ยนค่าของพารามิเตอร์ทีละตัวตามตารางด้านล่าง

ฉันใช้JMeterเพื่อสร้างคำขอเว็บพร้อมกัน 100 คำขอ (ดังที่แสดงถึงการใช้งานของเรา) ซ้ำ 10 10 ครั้ง แต่ละTestคำขอประกอบด้วย 1,000 คำขอทั้งหมด สิ่งนี้ส่งผลให้มีการเรียกฐานข้อมูลตามมา นี่แสดงให้เห็นว่า MySQL จะสร้างตารางชั่วคราวจำนวนมากโดยไม่คำนึงถึงพารามิเตอร์การกำหนดค่าที่เราเปลี่ยนแปลง

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

* ค่าเฉลี่ยของการรันสามครั้ง

ภาพด้านล่างแสดงถึงจำนวนหน่วยความจำและ CPU ที่เซิร์ฟเวอร์ฐานข้อมูลที่ต้องการสำหรับการกำหนดค่าต่างๆ เส้นสีดำแสดงค่าต่ำสุดและสูงสุดและแถบสีน้ำเงินระบุค่าเริ่มต้นและสิ้นสุด หน่วยความจำสูงสุด4096Mตามที่ระบุในคำถาม

การใช้ความจำ การใช้งาน CPU


เอ็นจิ้นการเก็บข้อมูลใดที่คุณใช้อยู่ MyiSAM หากคุณไม่ได้ใช้ตาราง MyISAM มันไม่มีความหมายที่จะต้องพึ่งพา key_buffer_size ถ้าคุณใช้เอ็นจิ้นการจัดเก็บ innodb ขนาดของ innodb_buffer_pool_size คืออะไร คุณใช้ query_cache หรือไม่
kasi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.