ในปัจจุบันมีการใช้งาน database กันอย่างแพร่หลายเป็นวงกว้าง โดย database ที่ได้รับความนิยมเป็นอันดับต้นๆ นั่นก็คือ MySQL
สำหรับในบนความนี้ จะกล่าวถึงเครื่องมือที่จะใช้ในการตรวจสอบประสิทธิภาพ การทำงานของ MySQL server คือ mysqlslap ซึ่งเป็นโปรแกรมที่เริ่มมีการใช้งานตั้งแต่ MySQL 5.1.4 ขึ้นไป โดยใช้ในการจำลองการใช้งาน สำหรับ MySQL เช่น กรณีที่มี connection หรือ มีการเรียกใช้งาน query จำนวนมาก ทั้งนี้เป็นการเตรียมการรองรับ connection ที่สูงขึ้น หรือหาแนวทางการแก้ไขปัญหาสำหรับกรณี ที่ database มีการเรียกใช้งานทรัพยากรสูงเกินกว่ากว่าระบบรองรับได้ สาเหตุอาจเกิดได้จากการออกแบบ database ที่ไม่สอดคล้องกับการใช้งาน ซึ่งอาจส่งผลกระทบกับระบบโดยรวมได้
สำหรับ mysqlslap นั้น จะสามารถวิเคราะห์และแสดงผล ตัวอย่าง ค่าเฉลี่ย, ค่าสูงสุดของเวลาที่ใช้ในการประมวลผลตามคำสั่งนั้นๆ ในบทความนี้ จะนำเสนอการทดสอบประสิทธิภาพของ database โดยใช้ mysqlslap ด้วยคำสั่ง พื้นฐานต่างๆ และแสดงผลการดำเนินการ
เตรียมการทดสอบด้วย
- Server ใช้งาน RAM 2 GB (CloudNode-M2G) สั่งซื้อได้ทาง https://www.hostpacific.com/cloudnode.html
- เลือกใช้งาน CentOS 7
หมายเหตุ
- เพื่อป้องกันผลกระทบจากการทดสอบ ผู้ทดสอบควรเลือกทดสอบบน server ที่ไม่มีการใช้งานจริง เนื่องจากการรับ connection และ query จำนวนมากในขณะทดสอบ อาจส่งผลกระทบต่อผู้ใช้งาน server ในขณะนั้นได้
- กรณีที่ต้องการทดสอบโดยใช้คำสั่งที่ซับซ้อน อาจะจำเป็นจะต้องใช้ resource ที่เพิ่มสูงขึ้น
ติดตั้งโปรแกรมเพื่อการทดสอบ
# mkdir /mysqlslap_test/ # cd /mysqlslap_test/
ติดตั้ง yum repository ของ mysql
# rpm -Uvh http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm Retrieving http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm Preparing... ################################# [100%] Updating / installing... 1:mysql-community-release-el7-5 ################################# [100%]
ตรวจสอบการติดตั้ง repository
# ls -la /etc/yum.repos.d/mysql* -rw-r--r-- 1 root root 1209 Jan 29 2014 /etc/yum.repos.d/mysql-community.repo -rw-r--r-- 1 root root 1060 Jan 29 2014 /etc/yum.repos.d/mysql-community-source.repo
ติดตั้ง mysql server และตรวจสอบ status เมื่อมีการติดตั้งเรียบร้อย
# yum –y install mysql-community-server # systemctl status mysqld.service mysqld.service - MySQL Community Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: inactive (dead)
สั่ง start service กำหนดให้ MySQL server เริ่มทำงานตั้งแต่มีการเปิดเครื่อง และกำหนดความปลอดภัยเบื้องต้นเพิ่มขึ้นให้กับ MySQL server
# systemctl start mysqld.service # systemctl enable mysqld.service # mysql_secure_installation … Enter current password for root (enter for none): [Enter ผ่านไป] … Set root password? [Y/n] Y New password: [ใส่ password ใหม่ที่ต้องการ] Re-enter new password: [ใส่ password ใหม่ที่ต้องการอีกครั้ง] Password updated successfully! Reloading privilege tables.. ... Success! … Remove anonymous users? [Y/n] Y Disallow root login remotely? [Y/n] Y Remove test database and access to it? [Y/n] Y Reload privilege tables now? [Y/n] Y Thanks for using MySQL!
หากแสดงข้อความดังกล่าว แสดงว่าดำเนินการเรียบร้อยแล้ว
ทดสอบ login จากนั้นตรวจสอบและปรับ connection ของ MySQL เพิ่มขึ้นเพื่อการทดสอบใช้งาน
# mysql -h localhost -u root -p Enter password: ใส่ค่า password ที่มีการกำหนดไว้ก่อนหน้านี้ Welcome to the MySQL monitor. Commands end with ; or \g ... mysql> # mysql -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. ... mysql> show variables like "max_connections"; ตรวจสอบค่า +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+ 1 row in set (0.00 sec) mysql> set global max_connections = 200; กำหนด connection ค่าเป็น 200 Query OK, 0 rows affected (0.00 sec) mysql> show variables like "max_connections"; ตรวจสอบค่าอีกครั้ง +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 200 | +-----------------+-------+ 1 row in set (0.00 sec) # และแก้ไขไฟล์ /etc/my.cnf โดยกำหนดไว้ภายใต้ section [mysqld] # vi /etc/my.cnf [mysqld] ... max_connections = 200 ...
เมื่อสามารถ login ได้เรียบร้อย เราจะสร้าง user สำหรับใช้ทดสอบแทนการใช้งาน root user ดังนี้
mysql> create user mysqladmin identified by 'Password'; Query OK, 0 rows affected (0.00 sec) mysql> grant all on *.* to mysqladmin; Query OK, 0 rows affected (0.00 sec)
ติดตั้ง database เพื่อใช้ในการทดสอบ โดยลองใช้ database ในการทดสอบ จาก MySQLtutorial.org
# cd /mysqlslap_test/ # wget http://www.mysqltutorial.org/wp-content/uploads/downloads/2016/05/ mysqlsampledatabase.zip # yum -y install unzip # unzip -x mysqlsampledatabase.zip
เริ่มติดตั้ง database classicmodels
# mysql -u mysqladmin -p < mysqlsampledatabase.sql Enter password: ใส่ค่า password ที่มีการกำหนดไว้ก่อนหน้านี้
เข้าตรวจสอบ เมื่อติดตั้ง database classicmodels เรียบร้อย
# mysql -u mysqladmin –p Enter password: ใส่ค่า password ที่มีการกำหนดไว้ก่อนหน้านี้ … mysql> use classicmodels; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed #แสดง table ต่างๆ mysql> show tables; +-------------------------+ | Tables_in_classicmodels | +-------------------------+ | customers | | employees | | offices | | orderdetails | | orders | | payments | | productlines | | products | +-------------------------+ 8 rows in set (0.00 sec) #ตรวจสอบรายละเอียดของ table mysql> describe payments; +----------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------+------+-----+---------+-------+ | customerNumber | int(11) | NO | PRI | NULL | | | checkNumber | varchar(50) | NO | PRI | NULL | | | paymentDate | date | NO | | NULL | | | amount | decimal(10,2) | NO | | NULL | | +----------------+---------------+------+-----+---------+-------+ 4 rows in set (0.00 sec) #ออกจากการใช้งาน mysql> quit;
จาก output ด้านบน จะเห็นได้ว่ามีการติดตั้ง database : classicmodels เรียบร้อยแล้ว และขั้นตอนต่อไป เราจะทำการทดสอบเรียกใช้งาน database
การทดสอบด้วย mysqlslap
ก่อนเริ่มการทดสอบ เราจะขอแนะนำ option บางส่วนสำหรับ mysqlslap เพื่อใช้ในการทดสอบ
-u, --user คือ user สำหรับติดต่อ database -p, --password คือ password ของ user ที่ใช้ในการติดต่อ database -P, --port คือ port ที่ใช้สำหรับเชื่อมต่อ database -h, --host คือ server ที่ต้องการเชื่อมต่อ -v, --verbose คือ ให้แสดงรายละเอียดต่างๆ เพิ่มเติมทาง output -a, --auto-generate-sql คือ กำหนดให้ mysql สร้างคำสั่งเองเพื่อการทดสอบขึ้นเอง --number-char-cols คือ จำนวนของ VARCHAR column ที่ใช้กำหนดสำหรับ option : --auto-generate-sql --number-int-cols คือ จำนวนของ INT column ที่ใช้กำหนดสำหรับ option : --auto-generate-sql -c, --concurrency คือ จำนวนของ client ที่ต้องการให้ระบบจำลอง เพื่อการทดสอบเรียกใช้งาน -i, --iterations คือ จำนวนครั้งที่ต้องการให้ เรียกคำสั่งเพื่อทดสอบ -F, --delimiter คือ ค่าที่ใช้ในการแยกชุดคำสั่งของ mysql --debug-info คือ ให้แสดงรายละเอียดเพิ่มเติม เช่น memory, cpu --engine คือ ประเภทในการ create table เช่น innodb หรือ myisam --create-schema คือ database ที่ต้องการทดสอบ --number-of-queries คือ ค่าจำกัดการ query ข้อมูลต่อ client --query คือ คำสั่งที่ต้องการเรียกใช้งาน ซึ่งสามารถกำหนดเป็นชุดคำสั่งหรือเป็นชื่อไฟล์ได้
เริ่มต้นการทดสอบ
ตัวอย่างที่ 1 : สำหรับการเริ่มต้น จะเป็นการจำลองการทดสอบเสมือน client 1 เครื่อง จากการสร้างคำสั่ง SQL ขึ้นโดยอัตโนมัติ
# mysqlslap --user=mysqladmin --password --host=localhost --auto-generate-sql --verbose Enter password: Benchmark Average number of seconds to run all queries: 0.010 seconds Minimum number of seconds to run all queries: 0.010 seconds Maximum number of seconds to run all queries: 0.010 seconds Number of clients running queries: 1 Average number of queries per client: 0
จะเห็นได้ว่า ค่า output ที่ออกมาจะแสดงถึงสถิติของเวลาที่ดำเนินการ query ข้อมูล เช่น
- ค่าเฉลียของการ run คำสั่ง คือ 0.010 วินาที
- ค่าน้อยที่สุดของการ run คำสั่ง คือ 0.010 วินาที
- ค่าสูงที่สุดของการ run คำสั่ง คือ 0.010 วินาที
- จำนวน client ที่มีการเรียกใช้งาน และ จำนวน query เฉลี่ยต่อ 1 client
- ตัวอย่างที่ 2 : จะมีการเพิ่มจำนวน client เป็น 10 connection และมีการเรียกคำสั่งจำนวน 100 ครั้ง
โดยในการทดสอบ ยังคงเป็นการสร้างคำสั่ง SQL ขึ้นโดยอัตโนมัติเช่นตัวอย่างแรก
# mysqlslap --user=mysqladmin --password --host=localhost --concurrency=10 --iterations=100 --auto-generate-sql --verbose Enter password: Benchmark Average number of seconds to run all queries: 0.027 seconds Minimum number of seconds to run all queries: 0.022 seconds Maximum number of seconds to run all queries: 0.038 seconds Number of clients running queries: 10 Average number of queries per client: 0
จากค่า output ที่ออกมาจะแสดง เช่น ค่าเฉลี่ยของ query ข้อมูลจาก 10 connection จะใช้เวลาสูงขึ้นในการดำเนินการ จากเดิมที่มีการใช้งานเพียงเครื่องเดียวเล็กน้อย ทั้งนี้การใช้งาน option –auto-generate-sql จะเป็นการสร้าง table ขนาดเล็กเพื่อทดสอบเท่านั้น ผู้ทดสอบสามารถกำหนดค่าของ table โดยใช้ option –number-char-cols และ –number-int-col ได้ ดังตัวอย่าง
ตัวอย่างที่ 3
# mysqlslap --user=mysqladmin --password --host=localhost --concurrency=10 --iterations=100 --auto-generate-sql --number-char-cols=50 --number-int-cols=5 --verbose Enter password: Benchmark Average number of seconds to run all queries: 0.117 seconds Minimum number of seconds to run all queries: 0.100 seconds Maximum number of seconds to run all queries: 0.187 seconds Number of clients running queries: 10 Average number of queries per client: 0
*ทั้งนี้การทดสอบเพิ่มจำนวน connection หรือ iteration ที่สูงขึ้น จะส่งผลต่อการเรียกใช้ resource ของ server ที่เพิ่มขึ้น*
หลังจากที่ได้มีการทดสอบด้วย การสร้างคำสั่งขึ้นโดยอัตโนมัติแล้ว ตัวอย่างต่อไป จะเป็นการทดสอบด้วย การกำหนดชุดคำสั่ง mysql ขึ้นเอง โดยจะเรียกใช้งาน database: classicmodels ซึ่งมีการติดตั้งไปก่อนหน้านี้
ตัวอย่างที่ 4 :
# mysqlslap --user=mysqladmin --password --host=localhost --concurrency=10 --iterations=1 --create-schema=classicmodels --query="SELECT * FROM orderdetails;" --verboseEnter password: Benchmark Average number of seconds to run all queries: 0.025 seconds Minimum number of seconds to run all queries: 0.025 seconds Maximum number of seconds to run all queries: 0.025 seconds Number of clients running queries: 10 Average number of queries per client: 1
ตัวอย่างที่ 5
# mysqlslap --user=mysqladmin --password --host=localhost --concurrency=10 --iterations=1 --number-of-queries=50 --create-schema=classicmodels --query="SELECT * FROM orderdetails;" --verbose Enter password: Benchmark Average number of seconds to run all queries: 0.161 seconds Minimum number of seconds to run all queries: 0.161 seconds Maximum number of seconds to run all queries: 0.161 seconds Number of clients running queries: 10 Average number of queries per client: 5
จากตัวอย่างที่ 4 และ 5 นั้น จะเห็นว่า มีการกำหนดค่าต่างๆ เช่นเดียวกัน โดยจะมี option ที่แตกต่างกันคือ –number-of-queries เท่านั้น ซึ่งการกำหนด number-of-queries จะมีผลให้เครื่อง client มีการ query ข้อมูลต่อ client เพิ่มขึ้น ดังนั้นค่าเวลาที่ได้จึงเพิ่มสูงขึ้นไปด้วย
จากตัวอย่างที่ผ่านมาจะเป็นการกำหนดคำสั่งเพียงคำสั่งเดียว แต่สำหรับ server ที่ใช้งานจริง จะมีรูปแบบชุดคำสั่งที่ซับซ้อนเพิ่มขึ้น ซึ่งเราสามารถเพิ่มชุดคำสั่งได้ เช่น
ตัวอย่างที่ 6 : เพิ่มชุดคำสั่งที่ใช้งานเป็น 2 ชุดคำสั่ง
# mysqlslap --user=mysqladmin --password --host=localhost --concurrency=10 --iterations=1 --number-of-queries=50 --create-schema=classicmodels --query="SELECT * FROM orderdetails; SELECT * FROM payments;" --verbose Enter password: Benchmark Average number of seconds to run all queries: 0.169 seconds Minimum number of seconds to run all queries: 0.169 seconds Maximum number of seconds to run all queries: 0.169 seconds Number of clients running queries: 10 Average number of queries per client: 5
ทั้งนี้หากมีชุดคำสั่งที่ต้องทดสอบเพิ่มมากขึ้น ผู้ทดสอบสามารถสร้างไฟล์ ชุดคำสั่งของ mysql ขึ้นก่อน แล้วจึงทำการสั่ง คำสั่งผ่าน command line เช่น
#echo "SELECT * FROM orderdetails;SELECT * FROM payments;SELECT * FROM orders;SELECT customers.customerNumber, customers.customerName, payments.checkNumber FROM customers, payments WHERE customers.country='USA' and customers.customerNumber = payments.customerNumber;” > /mysqlslap_test/test_query.sql
และทำการทดสอบด้วยคำสั่งดังนี้
# mysqlslap --user=mysqladmin --password --host=localhost --concurrency=50 --iterations=10 --number-of-queries=1000 --create-schema=classicmodels --query="/mysqlslap_test/ test_query.sql" --verbose --debug-info Enter password: Benchmark Average number of seconds to run all queries: 3.152 seconds Minimum number of seconds to run all queries: 2.803 seconds Maximum number of seconds to run all queries: 3.569 seconds Number of clients running queries: 50 Average number of queries per client: 20 User time 8.28, System time 1.95 Maximum resident set size 12824, Integral resident set size 0 Non-physical pagefaults 227342, Physical pagefaults 0, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 43983, Involuntary context switches 4
จากตัวอย่างนี้จะมีการใช้ option debug-info เพิ่มเติม ซึ่ง option นี้จะแสดงค่าของ CPU และ RAM ของ server ที่มีการเรียกใช้งาน และจะเห็นได้ว่าเมื่อมีการเพิ่มจำนวน connection และ number-of-queries ผลที่ได้คือเวลาที่เพิ่มขึ้นเป็น 3.152 วินาที โดยค่า Non-physical pagefaults จะอ้างอิงส่วนของ memory ว่าเพียงพอหรือไม่ และ context switches จะอ้างอิงข้อมูลของ CPU
ทั้งนี้ตัวอย่างที่นำเสนอไปด้านบน ผู้ดูแลระบบสามารถนำไปประยุกต์ ใช้ในการทดสอบเปรียบเทียบ โดยมีแนวทางดังนี้
- สามารถตรวจสอบหา คำสั่งต่างๆ ของ MySQL จาก server ที่ใช้งานได้จาก
- คำสั่ง “mysqladmin pro –v” จะแสดง process ของ mysql ทีมีการทำงานอยู่ในขณะนั้น และเป็นคำสั่งในรูปเต็ม
- สามารถเปิด slow query log เพื่อตรวจสอบหาคำสั่งที่ใช้งาน และนำมาใช้ในการทดสอบได้
- ทดสอบโดยการเปลี่ยน engine ที่ใช้งานระหว่าง innodb และ myisam ทั้งนี้ประเภทของ database อาจมีความเหมาะสมที่แตกต่างกันไป ซึ่งขึ้นอยู่กันการใช้ออกแบบและการใช้งาน
- ทดสอบทำ index หรือ key กับ field ที่มีการเรียกใช้งานบ่อย ซึ่งหลังจากการดำเนินการดังกล่าว การทำงานอาจเร็วขึ้นหรือไม่เปลี่ยนแปลง ทั้งนี้ขึ้นอยู่กับการออกแบบ database และคำสั่งที่เรียกใช้งาน
- เพื่อให้เห็นผลการทดสอบที่ชัดเจน ควรเลือกเครื่อง server สำหรับทดสอบให้มี spec ที่ใกล้เคียงกับเครื่องที่มีการใช้งานจริง
ทั้งนี้เมื่อมีการปรับค่าต่างๆ ที่เกี่ยวข้องแล้ว ผู้ดูแลระบบสามารถทดสอบประสิทธิภาพของ mysql ก่อนและหลังดำเนินการ เพื่อปรับปรุงให้ระบบดีขึ้นได้
ข้อมูลเพิ่มเติม: http://dev.mysql.com/doc/refman/5.5/en/mysqlslap.html