Benchmarking for MySQL

Keywords: Database MySQL SQL github

What is a benchmark

When we optimize the database, we only know if the optimization is effective by measuring the performance of the system. This measurement is benchmarking.Benchmark tests are defined as follows:

Benchmarking is the activity of measuring and evaluating software performance indicators to establish a performance benchmark at a time in order to reevaluate the impact of changes on performance when a system changes in software/hardware

We can think of it as follows:

Benchmarking is a type of stress test set up for the system and can be used to observe the behavior of the system under different pressures.Evaluate the capacity of the system and see how it processes different data.

But test-based testing is not equivalent to stress testing:

  • Test-based: Direct, simple, easy to compare, used to assess the processing power of a server.Benchmarks may not care about business logic, and the queries used and the authenticity of the business may have nothing to do with business processes
  • Stress testing: Testing real business data to get the pressure that a real system can withstand.Stress testing requires different topics, and the data and queries used are also true

The purpose of benchmarking MySQL is:

  • 1. Establish performance baseline of MySQL server to determine current MySQL server operation
  • 2. Simulate a higher load than the current system to find out the expansion bottleneck of the system.Increase database concurrency and observe changes in QPS and TPS to determine the relationship between concurrency quantity and optimal performance
  • 3. Testing different hardware, software and operating system configurations
  • 4. Verify that the new hardware device is properly configured

How to Benchmark

In general, there are two ways to benchmark:

  • 1. Benchmark the whole system: test from the entrance of the system (Web front-end of the website, APP front-end of the mobile phone)
    • Advantages: can test the performance of the entire system, including web server caches, databases, etc. can reflect the performance problems between the various component interfaces in the system, reflect the real performance status
    • Disadvantages: Complex and time consuming test case design
  • 2. Benchmark MySQL separately: only test MySQL services in the system
    • Advantages: Simple test case design and less time-consuming
    • Disadvantages: Unable to fully understand the performance baseline for the entire system

Common metrics for MySQL benchmarks:

  • Number of transactions processed per unit time (TPS)
  • Number of queries processed per unit time (QPS)
  • Concurrent Number: Number of query requests processed simultaneously
  • Response time of a single test task
    • Contains: average response time, minimum response time, maximum response time, and percentage of time

Easy to ignore in benchmarking:

  • When testing with production environment data, only part of the data is used, which may result in inaccurate test results
    • Recommendation: Use the full backup data of the database for testing
  • In a multi-user scenario, only single-user tests were performed
    • Recommended: Use multithreaded concurrency testing
  • Testing distributed applications on a single server
    • Recommendation: The same architecture should be used for testing
  • Repeatedly executing the same query, the problem is that the same SQL statement is easy to cache hits and does not reflect the true query performance.Queries may not be the same in real-world environments

Steps for benchmarking:

  • 1. Choosing whether to test the entire system or a component requires determining what data to use for testing.
  • 2. Preparing a collection script for test data usually requires collecting as much information as possible about the current system, such as CPU usage, IO, network traffic, status and counter information, etc.
  • 3. Write a script to analyze the benchmark information gathered in the second step and get the test results

Collect scripts and analyze script examples

Collection script for benchmark data:

# Run interval of script
# Create a storage directory for data files
mkdir -p $STORE_DIR
# Which directory will the collected data be stored in and the file prefix
# Set the running identity of the script
touch $RUNFILE && echo "1" > $RUNFILE
# mysql user name and password
# The path to the mysql command
MYSQL="/usr/local/mysql/bin/mysql -u$USER -p$PWD"
# Record global variables for the current mysql
$MYSQL -e "show global variables" >> mysql-variables

# The running identity file loops when it exists
while test -e $RUNFILE; do
    # Define the current time at which the script is running
    file=$(date +%F_%I)
    # Run the cycle at intervals
    sleep=$(date +%s.%N | awk '{print 5 - ($1 % 5)}')
    sleep $sleep

    ts="$(date +"TS %s.%N %F %T")"
    # Get system load information
    # Logging system load information
    echo "$ts $loadavg" >> $PREFIX-${file}-status
    # Record global variable information for the current mysql
    $MYSQL -e "show global status" >> $PREFIX-${file}-status &
    echo "$ts $loadavg" >> $PREFIX-${file}-innodbstatus
    # Record current innodb status information
    $MYSQL -e "show engine innodb status" >> $PREFIX-${file}-innodbstatus &
    echo "$ts $loadavg" >> $PREFIX-${file}-processlist
    # Record the list of all connection information for the current mysql
    $MYSQL -e "show full processlist\G" >> $PREFIX-${file}-processlist &
    echo $ts

echo Exiting because $RUNFILE does not exists

Test data analysis script:

awk '
   BEGIN {
     printf "#ts date time load QPS";
     fmt=" %.2f";
   /^TS/ {
   ts = substr($2,1,index($2,".")-1);
   load = NF -2;
   diff = ts - prev_ts;
   printf "\n%s %s %s %s",ts,$3,$4,substr($load,1,length($load)-1);
   printf fmt,($2-Queries)/diff;
   ' "$@"

### Use examples ###
# Sh. / ${test data file path}
# For example: sh. / /home/mysql/benchmarks/5-sec-status-2020-01-11_04-status

mysqlslap for Mysql Benchmarking Tool

In general, we don't script benchmarks on our own, because there are tools out there.For example, mysqlslap is a benchmarking tool that comes with versions above mysql 5.1.Since it is built-in and does not require a separate installation, the tool is located in the bin directory of mysql.

Functional introduction:

  • Simulate server load and output statistics
  • You can specify a query statement for a test, or you can use test statements that are automatically generated by the tool

Description of common parameters:

parameter Explain
--concurrency The number of concurrent clients, that is, the number of simulated clients, can be specified multiple, separated by commas
--iterations Specify the number of runs of the test
--auto-generate-sql Use system-generated SQL scripts for testing
--auto-generate-sql-add-autoincrement Add self-increasing ID s to automatically generated tables
--auto-generate-sql-load-type Specify the type of query used in the test (read, write, update, mixed), default mixed
--auto-generate-sql-write-number Specifies the amount of data generated when initializing the data
--engine To test the storage engine for tables, allow multiple designations, separated by commas
--no-drop Specify that test data is not cleaned up
--number-of-queries Specify the number of queries executed per connection
--debug-info Specify Output Extra Memory and CPU Statistics
--number-char-cols Specify the number of int types contained in the test table
--number-int-cols Specify the number of varchar types contained in the test table
--create-schema Specify the name of the database used to execute the test
--query SQL script for specifying custom
--only-print When this parameter is specified, the test script is not run, but the generated script is printed out

Example use:

[root@localhost ~]# mysqlslap -uroot -p123456 --concurrency=1,50,100,200 --iterations=3 --number-int-cols=5 --number-char-cols=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=myisam,innodb --number-of-queries=10 --create-schema=test

After running the test, some of the output snippets intercepted are as follows:

    # Run tests for the myisam engine
    Running for engine myisam
    # Average seconds to run all queries
    Average number of seconds to run all queries: 0.020 seconds
    # Minimum seconds to run all queries
    Minimum number of seconds to run all queries: 0.018 seconds
    # Maximum number of seconds to run all queries
    Maximum number of seconds to run all queries: 0.022 seconds
    # Number of clients running queries
    Number of clients running queries: 1
    # Average number of queries per client 
    Average number of queries per client: 10

    Running for engine innodb
    Average number of seconds to run all queries: 0.049 seconds
    Minimum number of seconds to run all queries: 0.042 seconds
    Maximum number of seconds to run all queries: 0.059 seconds
    Number of clients running queries: 1
    Average number of queries per client: 10

sysbench of Mysql benchmarking tool

In addition to mysqlslap, a native benchmarking tool for mysql, sysbench is a common tool.Sysbench has more features than mysqlslap and is more comprehensive to test.In addition to testing MySQL, sysbench can also test CPU, IO, memory and other aspects of the system.

Install sysbench

The GitHub repository address and source installation documentation for sysbench are as follows:

In general, the sysbench tool will not come with the system, we need to install it by ourselves. I will install it here by compiling and installing the source code.First, copy the download link of the source package to the following address:

Then download it on Linux using the wget command:

[root@txy-server ~]# cd /usr/local/src
[root@txy-server /usr/local/src]# wget

Install some of the libraries on which sysbench is compiled:

[root@txy-server /usr/local/src]# yum -y install make automake libtool pkgconfig libaio-devel mariadb-devel openssl-devel

The downloaded source package is then decompressed and entered into the decompressed directory:

[root@txy-server /usr/local/src]# tar -zxvf 1.0.19.tar.gz
[root@txy-server /usr/local/src]# cd sysbench-1.0.19/

Finally, complete the compilation and installation with the following steps:

[root@txy-server /usr/local/src/sysbench-1.0.19]# ./
[root@txy-server /usr/local/src/sysbench-1.0.19]# ./configure --with-mysql-includes=/usr/local/mysql/include --with-mysql-libs=/usr/local/mysql/lib
[root@txy-server /usr/local/src/sysbench-1.0.19]# make && make install

After waiting for the compilation installation to complete, test whether the installation was successful.I have reported here an error that the library file could not be found:

[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version
sysbench: error while loading shared libraries: cannot open shared object file: No such file or directory

The solution is to set up a soft connection to the file in / usr/lib64 / directory:

[root@txy-server /usr/local/src/sysbench-1.0.19]# ln -s /usr/local/mysql/lib/  /usr/lib64/

Test again and execute successfully:

[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version
sysbench 1.0.19

Use of sysbench

The command format for sysbench is as follows:

sysbench [options]... [testname] [command] 

1. options are the specified test parameters. The following are commonly used parameters when testing MySQL with sysbench:

  • --mysql-db: The name of the database used to specify the benchmark, which must already exist
  • --mysql_storage_engine: MySQL storage engine for the specified test
  • --tables: Number of tables that execute tests
  • --table_size: Specifies the amount of data in each table
  • --threads: Specifies the number of concurrent threads for the test
  • --max-time: Specify the maximum test time in seconds
  • --report-interval: Output statistics once in seconds at a specified interval
  • --mysql-socket: Specifies the path to the.sock file of Mysql to connect to MySQL
  • --mysql-user: Specify the user to connect to MySQL for testing
  • --mysql-password: Specify the password for the MySQL user
  • For more information on other parameters Official Documents

2. Tesname is the specified built-in test type or test script.The built-in test types have the following values:

  • fileio: Test file system I/O performance
  • cpu: test cpu performance
  • Memory: test memory performance
  • threads: testing thread performance
  • Mutex: test mutex performance
  • Executing sysbench [testname] help allows you to view the parameters supported by each test type

Test scripts need to be specified for tests other than built-in test types.The test script for sysbench needs to be written in lua language. You can write your own test script according to your actual needs, or you can use the test script that comes with sysbench.The lua script that comes with sysbench is as follows:

[root@txy-server ~]# ls /usr/local/share/sysbench
bulk_insert.lua  # Used to test a large number of insert operation performance
oltp_common.lua  # Public files, referenced by other scripts, not available directly
oltp_delete.lua  # Used to test delete operation performance under oltp
oltp_insert.lua  # Used to test insert operation performance under oltp
oltp_point_select.lua   # Used to test the performance of fixed-point queries under oltp, such as queries based on primary keys
oltp_read_only.lua   # Used to test read-only performance under oltp
oltp_read_write.lua  # Used to test read and write performance under oltp
oltp_update_index.lua  # Used to test the performance of updating index fields
oltp_update_non_index.lua  # Used to test the performance of updating indexed field operations
oltp_write_only.lua  # Used to test write performance under oltp
select_random_points.lua  # Used to test the performance of random fixed-point queries
select_random_ranges.lua  # Used to test random range read performance
  • Tips: Different versions of sysbench may have different paths to store test scripts and need to confirm themselves

3. command specifies some test actions, such as running tests, clearing data or preparing data, etc.

  • Prepare: used to prepare test data before the test starts
  • run: execute the test when the test data is ready
  • Cleaup: Used to clean up test data after test execution is complete

sysbench benchmark example

1. Testing CPU performance

The following commands let the cpu find prime numbers within 10,000 and count the time required to calculate them to see how well the cpu performs.It is important to note that this approach tests single-core performance rather than multicore performance:

[root@txy-server ~]# sysbench --cpu-max-prime=10000 cpu run

The test results are as follows:

# CPU speed
CPU speed:
    # Number of events per second
    events per second:  1039.79

General statistics:
    # Calculate the total time spent on all prime numbers
    total time:                          10.0005s  
    # Total number of events
    total number of events:              10400

Latency (ms):
         # Calculate the minimum time spent on a prime number
         min:                                    0.94
         # Average time to compute a prime number
         avg:                                    0.96
         # Calculate the maximum time spent on a prime number
         max:                                    9.43
         # 95% of cases are 1.01 milliseconds calculating a prime number
         95th percentile:                        1.01
         # Total time consumed
         sum:                                 9994.05

# Thread fairness
Threads fairness:
    events (avg/stddev):           10400.0000/0.00
    execution time (avg/stddev):   9.9941/0.00

2. Test system I/O performance

To test I/O performance, test data needs to be prepared, and the size of test data needs to be larger than physical memory.The commands are as follows:

# This command generates 127 test files of a total size of 4G
[root@txy-server ~]# sysbench --file-total-size=4G fileio prepare
Creating file test_file.125
Creating file test_file.126
Creating file test_file.127
4294967296 bytes written in 39.00 seconds (105.04 MiB/sec).
[root@txy-server ~]#

When the data is ready, execute the test:

[root@txy-server ~]# sysbench --threads=8 --file-total-size=4G --file-test-mode=rndrw --report-interval=1 fileio run

Parameter description:

  • --threads=8: Set the number of concurrent threads to 8
  • --file-test-mode=rndrw: Specifies that the file test mode is random read-write, i.e. tests the random read-write performance of disk I/O
  • --report-interval=1: Specifies that statistics are output once per second

The test results are as follows:

File operations:
    reads/s:                      2089.75
    writes/s:                     1392.67
    fsyncs/s:                     4553.64

    # Read per second
    read, MiB/s:                  32.65
    written, MiB/s:               21.76

General statistics:
    total time:                          10.0778s
    total number of events:              79973

Latency (ms):
         min:                                    0.00
         avg:                                    1.00
         max:                                   58.42
         95th percentile:                        3.13
         sum:                                79895.62

Threads fairness:
    events (avg/stddev):           9996.6250/43.23
    execution time (avg/stddev):   9.9870/0.01

Finally, clean up the test data:

[root@txy-server ~]# sysbench --file-total-size=4G fileio cleanup

3. Testing MySQL performance

Since the test type built into sysbench does not have MySQL, when testing MySQL with sysbench, the testname needs to be specified as the path to the test script.Sysbench comes with some MySQL test scripts, so we don't need to write our own test scripts without special needs.Next, do a simple demonstration to see how to use test scripts to test MySQL performance.

First and foremost, you need to prepare the data with the following commands:

[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua prepare
  • Tips: This script is used to test the read and write performance under OLTP.In addition, the author here uses the root account directly for convenience. In the actual test, it is important to create an account for the test.

Perform tests:

[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua run

The test results are as follows:

SQL statistics:
    queries performed:
        # Total number of read operations
        read:                            10444
        # Total number of write operations
        write:                           2984
        # Total number of other operations, such as commit, etc.
        other:                           1492
        # Total number of operations performed
        total:                           14920
    # The number of transactions executed per second, TPS, here 74.48 per second
    transactions:                        746    (74.48 per sec.)
    # The number of queries per second, QPS, here 1489.53 per second
    queries:                             14920  (1489.53 per sec.)
    # Number of errors ignored
    ignored errors:                      0      (0.00 per sec.)
    # Number of reconnections
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          10.0150s
    total number of events:              746

Latency (ms):
         min:                                    8.86
         avg:                                   13.42
         max:                                   99.97
         95th percentile:                       20.00
         sum:                                10009.79

Threads fairness:
    events (avg/stddev):           746.0000/0.00
    execution time (avg/stddev):   10.0098/0.00

Again, the final step is to clean up the test data:

[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua cleanup

If you want to know which parameters the test script specifically supports, you can view them the same way as the built-in test type, just by replacing the name of the test type with the script:

[root@txy-server ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua help

Posted by dsdsdsdsd on Sun, 12 Jan 2020 08:50:37 -0800