前書き
MySQLには、バージョン5.1.4以降に存在する* mysqlslap *と呼ばれる便利な小さな診断ツールが付属しています。 DBAと開発者がデータベースサーバーの負荷テストを行うのに役立つベンチマークツールです。
mysqlslapは、データベースサーバーに同時にアクセスする多数のクライアント接続をエミュレートできます。 負荷テストのパラメーターは完全に構成可能であり、さまざまなテスト実行の結果を使用して、データベース設計またはハードウェアリソースを微調整できます。
このチュートリアルでは、mysqlslapを使用して基本的なクエリでMySQLデータベースをロードテストする方法を学習し、ベンチマークがこれらのクエリの微調整にどのように役立つかを確認します。 いくつかの基本的なデモンストレーションの後、テスト用に既存のデータベースのコピーを作成し、ログからクエリを収集し、スクリプトからテストを実行する、かなり現実的なテストシナリオを実行します。
このチュートリアルに示されているコマンド、パッケージ、およびファイルは、* CentOS 7 *でテストされています。 他のディストリビューションでも概念は同じです。
どのサイズのサーバーを使用すればよいですか?
特定のデータベースサーバーのベンチマークに関心がある場合は、同じ仕様で、データベースの正確なコピーがインストールされているサーバーでテストする必要があります。
学習目的でこのチュートリアルを実行し、その中のすべてのコマンドを実行する場合は、少なくとも* 2 GB *のドロップレットをお勧めします。 このチュートリアルのコマンドはサーバーに負担をかけることを目的としているため、小さなサーバーではタイムアウトになることがあります。
このチュートリアルのサンプル出力は、教育用の例を最適化するためにさまざまな方法で作成されました。
ステップ1-テストシステムにMySQL Community Serverをインストールする
まず、テストデータベースにMySQL Community Serverの新しいコピーをインストールします。 このチュートリアルのコマンドやクエリを運用データベースサーバーで実行しないでください。
これらのテストは、テストサーバーに負荷をかけることを目的としており、運用サーバーで遅延やダウンタイムを引き起こす可能性があります。 このチュートリアルは、次の環境でテストされました。
-
CentOS 7
-
2 GBのドロップレットを推奨。このチュートリアルに示されているベンチマーク結果は、教育目的のために作成されたものであり、特定のDigitalOceanベンチマークを反映していないことに注意してください。
最初に、このチュートリアルに関連するすべてのファイルを保持するディレクトリを作成します。 これは物事を整理するのに役立ちます。 次のディレクトリに移動します。
sudo mkdir /mysqlslap_tutorial
cd /mysqlslap_tutorial
次に、MySQL Community Release yumリポジトリをダウンロードします。 ダウンロードしているリポジトリは、CentOS 7で動作するRed Hat Enterprise Linux 7用です。
sudo wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
次に、 `+ rpm -Uvh +`コマンドを実行してリポジトリをインストールできます。
sudo rpm -Uvh mysql-community-release-el7-5.noarch.rpm
`+ / etc / yum.repos.d +`フォルダーの内容を見て、リポジトリがインストールされていることを確認します。
sudo ls -l /etc/yum.repos.d
出力は次のようになります。
-rw-r--r--. 1 root root 1612 Jul 4 21:00 CentOS-Base.repo
-rw-r--r--. 1 root root 640 Jul 4 21:00 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 1331 Jul 4 21:00 CentOS-Sources.repo
-rw-r--r--. 1 root root 156 Jul 4 21:00 CentOS-Vault.repo
-rw-r--r--. 1 root root 1209 Jan 29 2014 mysql-community.repo
-rw-r--r--. 1 root root 1060 Jan 29 2014 mysql-community-source.repo
正しいMySQLリリースがインストールに対して有効になっていることも確認できます。
sudo yum repolist enabled | grep mysql
私たちの場合、* MySQL 5.6 Community Server *が私たちが望んでいたものです。
mysql-connectors-community/x86_64 MySQL Connectors Community 10
mysql-tools-community/x86_64 MySQL Tools Community 6
mysql56-community/x86_64 MySQL 5.6 Community Server 64
MySQL Community Serverをインストールします。
sudo yum install mysql-community-server
プロセスが完了したら、インストールされているコンポーネントを確認しましょう。
sudo yum list installed | grep mysql
リストは次のようになります。
mysql-community-client.x86_64 5.6.20-4.el7 @mysql56-community
mysql-community-common.x86_64 5.6.20-4.el7 @mysql56-community
mysql-community-libs.x86_64 5.6.20-4.el7 @mysql56-community
mysql-community-release.noarch el7-5 installed
mysql-community-server.x86_64 5.6.20-4.el7 @mysql56-community
次に、MySQLデーモンが実行中であり、サーバーの起動時に自動的に起動することを確認する必要があります。 mysqldデーモンのステータスを確認します。
sudo systemctl status mysqld.service
停止している場合、次の出力が表示されます。
mysqld.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; disabled)
Active: inactive (dead)
サービスを開始します。
sudo systemctl start mysqld.service
起動時に自動起動するように設定されていることを確認してください。
sudo systemctl enable mysqld.service
最後に、MySQLを保護する必要があります。
sudo mysql_secure_installation
これにより、一連のプロンプトが表示されます。 以下にプロンプトを表示し、回答を入力します。 最初はMySQLルートユーザーのパスワードがないため、* Enter *を押してください。
プロンプトで、自分で選択する必要のある新しいセキュアルートパスワードを入力する必要があります。 * y *と答えて、匿名データベースユーザーアカウントを削除したり、リモートルートログインを無効にしたり、特権テーブルを再ロードしたりする必要があります。
...
Enter current password for root (enter for none):
OK, successfully used password, moving on...
...
Set root password? [Y/n]
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!
...
Remove anonymous users? [Y/n]
... Success!
...
Disallow root login remotely? [Y/n]
... Success!
Remove test database and access to it? [Y/n]
- Dropping test database...
... Success!
...
Reload privilege tables now? [Y/n]
... Success!
Cleaning up...
これでデータベースに接続し、すべてが機能していることを確認できます。
sudo mysql -h localhost -u root -p
プロンプトで設定したばかりのルートMySQLパスワードを入力します。 次のような出力が表示されるはずです。
Enter password:
Welcome to the MySQL monitor....
mysql>
プロンプトで、コマンドを入力してすべてのデータベースを表示します。
show databases;
次のような出力が表示されるはずです。
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)
最後に、というユーザーアカウントを作成しましょう。 このアカウントは、rootユーザーの代わりにMySQLにログインするために使用されます。 このユーザーの自分のパスワードに置き換えてください。 また、このアカウントにすべての特権を付与します。 MySQLプロンプトで、次のコマンドを入力します。
create user sysadmin identified by '';
出力:
Query OK, 0 rows affected (0.00 sec)
特権を付与します。
grant all on *.* to sysadmin;
出力:
Query OK, 0 rows affected (0.01 sec)
ここで、オペレーティングシステムのプロンプトに戻りましょう。
quit;
出力:
Bye
ステップ2-サンプルデータベースのインストール
次に、テスト用のサンプルデータベースをインストールする必要があります。 このデータベースは* employees *と呼ばれ、http://dev.mysql.com/doc/index-other.html [MySQL Webサイトから自由にアクセス可能]です。 データベースはhttps://launchpad.net/test-db/[Launchpad]からダウンロードすることもできます。 従業員データベースは、Patrick CrewsとGiuseppe Maxiaによって開発されました。 元のデータは、Siemens Corporate ResearchのFusheng WangとCarlo Zanioloによって作成されました。
大規模なデータセットを備えているため、従業員データベースを選択しています。 データベース構造は非常にシンプルです。テーブルは6つしかありません。しかし、そこに含まれるデータには3,000,000を超える従業員レコードがあります(給与テーブル自体には300万行近くあります)。 これにより、より現実的な本番ワークロードをエミュレートできます。
まず、ディレクトリにいることを確認しましょう:
cd /mysqlslap_tutorial
従業員サンプルデータベースの最新バージョンをダウンロードします。
sudo wget https://launchpad.net/test-db/employees-db-1/1.0.6/+download/employees_db-full-1.0.6.tar.bz2
アーカイブを解凍できるようにbzip2ツールをインストールします。
sudo yum install bzip2
データベースアーカイブを解凍します。 これには1分かかります。 ここでは、2つのステップでそれを行っています。
sudo bzip2 -dfv employees_db-full-1.0.6.tar.bz2
sudo tar -xf employees_db-full-1.0.6.tar
内容は、と呼ばれる別の新しいディレクトリに解凍されます。 データベースをインストールするクエリを実行するには、このディレクトリに移動する必要があります。 内容には、READMEドキュメント、変更ログ、データダンプ、およびデータベース構造を作成するさまざまなSQLクエリファイルが含まれます。
cd employees_db
ls -l
表示される内容は次のとおりです。
-rw-r--r--. 1 501 games 752 Mar 30 2009 Changelog
-rw-r--r--. 1 501 games 6460 Oct 9 2008 employees_partitioned2.sql
-rw-r--r--. 1 501 games 7624 Feb 6 2009 employees_partitioned3.sql
-rw-r--r--. 1 501 games 5660 Feb 6 2009 employees_partitioned.sql
-rw-r--r--. 1 501 games 3861 Nov 28 2008 employees.sql
-rw-r--r--. 1 501 games 241 Jul 30 2008 load_departments.dump
-rw-r--r--. 1 501 games 13828291 Mar 30 2009 load_dept_emp.dump
-rw-r--r--. 1 501 games 1043 Jul 30 2008 load_dept_manager.dump
-rw-r--r--. 1 501 games 17422825 Jul 30 2008 load_employees.dump
-rw-r--r--. 1 501 games 115848997 Jul 30 2008 load_salaries.dump
-rw-r--r--. 1 501 games 21265449 Jul 30 2008 load_titles.dump
-rw-r--r--. 1 501 games 3889 Mar 30 2009 objects.sql
-rw-r--r--. 1 501 games 2211 Jul 30 2008 README
-rw-r--r--. 1 501 games 4455 Mar 30 2009 test_employees_md5.sql
-rw-r--r--. 1 501 games 4450 Mar 30 2009 test_employees_sha.sql
次のコマンドを実行してMySQLに接続し、データベースを作成してデータをロードするスクリプトを実行します。
sudo mysql -h localhost -u sysadmin -p -t < employees.sql
プロンプトで、前のセクションで* sysadmin * MySQLユーザー用に作成したパスワードを入力します。
プロセス出力は次のようになります。 実行には1分ほどかかります。
+-----------------------------+
| INFO |
+-----------------------------+
| CREATING DATABASE STRUCTURE |
+-----------------------------+
+------------------------+
| INFO |
+------------------------+
| storage engine: InnoDB |
+------------------------+
+---------------------+
| INFO |
+---------------------+
| LOADING departments |
+---------------------+
+-------------------+
| INFO |
+-------------------+
| LOADING employees |
+-------------------+
+------------------+
| INFO |
+------------------+
| LOADING dept_emp |
+------------------+
+----------------------+
| INFO |
+----------------------+
| LOADING dept_manager |
+----------------------+
+----------------+
| INFO |
+----------------+
| LOADING titles |
+----------------+
+------------------+
| INFO |
+------------------+
| LOADING salaries |
+------------------+
これで、MySQLにログインし、いくつかの基本的なクエリを実行して、データが正常にインポートされたことを確認できます。
sudo mysql -h localhost -u sysadmin -p
-
sysadmin * MySQLユーザーのパスワードを入力します。
新しいデータベースのデータベースのリストを確認します。
show databases;
出力:
+--------------------+
| Database |
+--------------------+
| information_schema |
| employees |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.01 sec)
従業員データベースを使用します。
use employees;
その中のテーブルを確認します。
show tables;
出力:
+---------------------+
| Tables_in_employees |
+---------------------+
| departments |
| dept_emp |
| dept_manager |
| employees |
| salaries |
| titles |
+---------------------+
6 rows in set (0.01 sec)
必要に応じて、これらの各テーブルの詳細を確認できます。 テーブルの情報を確認します。
describe titles;
出力:
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| title | varchar(50) | NO | PRI | NULL | |
| from_date | date | NO | PRI | NULL | |
| to_date | date | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
エントリ数を確認します。
mysql> select count(*) from titles;
+----------+
| count(*) |
+----------+
| 443308 |
+----------+
1 row in set (0.14 sec)
必要な他のデータを確認します。 これで、オペレーティングシステムのプロンプトに戻ることができます。
quit;
ステップ3-mysqlslapの使用
mysqlslapの使用を開始できます。 mysqlslapは通常のシェルプロンプトから呼び出すことができるため、MySQLに明示的にログインする必要はありません。 ただし、このチュートリアルでは、Linuxサーバーへの別のターミナル接続を開いて、前に作成した* sysadmin *ユーザーと新しいMySQLセッションを開始します。これにより、MySQLのいくつかの項目をより簡単に確認および更新できます。 そのため、sudoユーザーに対して1つのプロンプトを開き、1つのプロンプトをMySQLにログインします。
テスト用の特定のコマンドに入る前に、この最も有用なmysqlslapオプションのリストをご覧ください。 これは、後で独自のmysqlslapコマンドを設計するのに役立ちます。
Option | What it means |
---|---|
–user |
MySQL username to connect to the database server |
–password |
Password for the user account. It’s best to leave it blank in command line |
–host |
MySQL database server name |
–port |
Port number for connecting to MySQL if the default is not used |
–concurrency |
The number of simultaneous client connections mysqlslap will emulate |
–iterations |
The number of times the test query will be run |
–create-schema |
The schema in which to run the tests |
–query |
The query to execute. This can either be a SQL query string or a path to a SQL script file |
–create |
The query to create a table. Again, this can be a query string or a path to a SQL file |
–delimiter |
The delimiter used to separate multiple SQL statements |
–engine |
The MySQL database engine to use (e.g., InnoDB) |
–auto-generate-sql |
Lets MySQL perform load testing with its own auto-generated SQL command |
ユースケース:自動生成されたSQLおよびデータを使用したベンチマーク
mysqlslapのauto-generate-sql機能を使用することから始めます。 自動生成されたSQLを使用すると、mysqlslapは適切なmysqlslapと呼ばれる別の一時データベースを作成します。 このデータベースには、サンプルデータが入力された1つの整数と1つのvarchar型の列を持つ単純なテーブルがあります。 これは、データベースサーバーの全体的なパフォーマンスを確認するための迅速かつ簡単な方法です。
自動生成されたSQLを1回繰り返して、単一のクライアント接続をテストすることから始めます。
sudo mysqlslap --user=sysadmin --password --host=localhost --auto-generate-sql --verbose
出力は次のようになります。
Benchmark
Average number of seconds to run all queries: 0.009 seconds
Minimum number of seconds to run all queries: 0.009 seconds
Maximum number of seconds to run all queries: 0.009 seconds
Number of clients running queries: 1
Average number of queries per client: 0
mysqlslapは、出力に示されているいくつかのベンチマーク統計を報告します。 クエリの実行にかかった平均秒数、最小秒数、最大秒数を報告します。 また、この負荷テストに使用されたクライアント接続の数は1つであることがわかります。
50の同時接続を試行し、自動生成されたクエリを10回実行します。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=50 --iterations=10 --auto-generate-sql --verbose
このコマンドの意味するところは、50のシミュレートされたクライアント接続がそれぞれ同じテストクエリを同時にスローし、このテストが10回繰り返されることです。
出力は、増加した負荷との顕著な違いを示しています。
Benchmark
Average number of seconds to run all queries: 0.197 seconds
Minimum number of seconds to run all queries: 0.168 seconds
Maximum number of seconds to run all queries: 0.399 seconds
Number of clients running queries: 50
Average number of queries per client: 0
フィールドの値が50になっていることに注意してください。 クライアントごとのクエリの平均数はゼロです。
自動生成されたSQLは、2つのフィールドを持つ単純なテーブルを作成します。 ほとんどの実稼働環境では、テーブル構造はそれよりはるかに大きくなります。 テストテーブルにフィールドを追加することで、これをエミュレートするようmysqlslapに指示できます。 そのために、2つの新しいパラメーター、「-number-char-cols +」と「-number-int-cols +」を使用できます。 これらのパラメーターは、テストテーブルに追加する列のvarchar型とint型の数を指定します。
次の例では、5つの数値列と20の文字型列を持つテーブルに対して実行される自動生成されたSQLクエリでテストしています。 また、50のクライアント接続をシミュレートしているため、テストを100回繰り返す必要があります。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=50 --iterations=100 --number-int-cols=5 --number-char-cols=20 --auto-generate-sql --verbose
これには少し時間がかかります。 テストの実行中に、MySQLセッションが実行されている他のターミナルウィンドウに切り替えて、何が起こっているかを確認できます。 待機時間が長すぎると、テストが完了し、テストデータベースを表示できなくなることに注意してください。
MySQLプロンプトから:
show databases;
データベースに注意してください:
+--------------------+
| Database |
+--------------------+
| information_schema |
| employees |
| mysql |
| mysqlslap |
| performance_schema |
+--------------------+
5 rows in set (0.01 sec)
必要に応じて、テストデータベースのテーブルを確認できます。 * t1 *と呼ばれます。
他のターミナルウィンドウをもう一度確認します。 テストが終了すると、負荷が増加するにつれてパフォーマンスがさらに低下していることがわかります。
Benchmark
Average number of seconds to run all queries: 0.695 seconds
Minimum number of seconds to run all queries: 0.627 seconds
Maximum number of seconds to run all queries: 1.442 seconds
Number of clients running queries: 50
Average number of queries per client: 0
MySQLターミナルセッションに戻ります。 mysqlslapが使い捨てデータベースを削除したことがわかります。 MySQLプロンプトで:
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| employees |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
ユースケース:カスタムクエリを使用したベンチマーク
自動生成されたSQLは、サーバーの物理リソースを評価する場合に適しています。 特定のシステムが受けることができる負荷のレベルを見つけたいときに役立ちます。
ただし、特定のデータベース依存アプリケーションのパフォーマンスをトラブルシューティングする場合は、実際のデータで実際のクエリをテストする必要があります。 これらのクエリは、Webサーバーまたはアプリケーションサーバーからのものである可能性があります。
ここでは、テストする特定のクエリを知っていると仮定します。 次のセクションでは、サーバーで実行されているクエリを見つける方法を示します。
インラインクエリから始めます。 オプションを使用して、mysqlslapにインラインクエリを指定できます。 SQLステートメントに改行を含めることはできません。また、セミコロン(;)で区切る必要があります。 クエリも二重引用符で囲む必要があります。
次のコードスニペットでは、テーブルに対して簡単なクエリを実行しています。 `deptemp`テーブルには30万件を超えるレコードがあります。 オプションを使用してデータベースを指定した方法に注意してください。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=50 --iterations=10 --create-schema=employees --query="SELECT * FROM dept_emp;" --verbose
これには実行に時間がかかります。 1〜2分後に、このようなパフォーマンスベンチマークを受け取るはずです。
Benchmark
Average number of seconds to run all queries: 18.486 seconds
Minimum number of seconds to run all queries: 15.590 seconds
Maximum number of seconds to run all queries: 28.381 seconds
Number of clients running queries: 50
Average number of queries per client: 1
(注:このクエリが10分以上ハングするか、何も出力されない場合は、および/またはの数値を小さくして再試行するか、より大きなサーバーで再試行してください。)
次に、パラメーターで複数のSQLステートメントを使用します。 次の例では、各クエリをセミコロンで終了しています。 mysqlslapは、オプションを指定したため、多数の個別のSQLコマンドを使用していることを認識しています。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=20 --iterations=10 --create-schema=employees --query="SELECT * FROM employees;SELECT * FROM titles;SELECT * FROM dept_emp;SELECT * FROM dept_manager;SELECT * FROM departments;" --delimiter=";" --verbose
このテストでは、同じ数の接続と同じ回数の反復を使用します。 ただし、複数のSELECTステートメントのパフォーマンスは徐々に低下しました(平均23.8秒vs. 18.486秒):
Benchmark
Average number of seconds to run all queries: 23.800 seconds
Minimum number of seconds to run all queries: 22.751 seconds
Maximum number of seconds to run all queries: 26.788 seconds
Number of clients running queries: 20
Average number of queries per client: 5
実動SQLステートメントは複雑になる場合があります。 テスト用に入力するよりも、複雑なSQLステートメントをスクリプトに追加する方が簡単です。 そのため、mysqlslapにスクリプトファイルからクエリを読み取るように指示できます。
これを説明するために、SQLコマンドからスクリプトファイルを作成しましょう。 以下のコードスニペットを使用して、このようなファイルを作成できます。
sudo echo "SELECT * FROM employees;SELECT * FROM titles;SELECT * FROM dept_emp;SELECT * FROM dept_manager;SELECT * FROM departments;" > ~/select_query.sql
sudo cp ~/select_query.sql /mysqlslap_tutorial/
このファイルには、5つのSELECTステートメントがすべて含まれています。
このスクリプトには複数のクエリがあるため、新しいテストコンセプトを導入できます。 mysqlslapはクエリを「並列化」できます。 これを行うには、各テストクライアントが実行するクエリの数を指定します。 mysqlslapはオプションでこれを行います。 したがって、実行する接続数が50でクエリ数が1000の場合、各クライアントはそれぞれ約20のクエリを実行します。
最後に、スイッチを使用することもできます。これにより、使用されているコンピューティングリソースが示されます。
次のコードスニペットでは、作成したスクリプトファイルを使用するようにmysqlslapに要求しています。 パラメータも指定しています。 このプロセスは2回繰り返され、出力にデバッグ情報が必要になります。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=20 --number-of-queries=1000 --create-schema=employees --query="/mysqlslap_tutorial/select_query.sql" --delimiter=";" --verbose --iterations=2 --debug-info
このコマンドが完了すると、興味深い結果が得られます。
Benchmark
Average number of seconds to run all queries: 217.151 seconds
Minimum number of seconds to run all queries: 213.368 seconds
Maximum number of seconds to run all queries: 220.934 seconds
Number of clients running queries: 20
Average number of queries per client: 50
User time 58.16, System time 18.31
Maximum resident set size 909008, Integral resident set size 0
Non-physical pagefaults 2353672, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 102785, Involuntary context switches 43
ここでは、MySQLインスタンスですべてのクエリを実行する平均秒数は217秒で、ほぼ4分です。 これは、仮想マシンで使用可能なRAMとCPUの量の影響を確実に受けましたが、中程度の数のクライアント接続からのクエリが2回繰り返されることも原因でした。
非物理的なページフォールトが多数発生したことがわかります。 ページフォールトは、メモリ内にデータが見つからず、システムがディスク上のスワップファイルからデータを取得する必要がある場合に発生します。 出力には、CPU関連の情報も表示されます。 この場合、多数のコンテキストスイッチが表示されます。
ユースケース:実用的なベンチマークシナリオとライブクエリのキャプチャ
これまでの例では、元の従業員データベースに対してクエリを実行してきました。 これは、DBAがあなたに望んでいないことです。 そして、それには十分な理由があります。 実稼働データベースのロードを追加したり、実稼働テーブルのデータを削除、更新、挿入する可能性のあるテストクエリを実行したりする必要はありません。
実稼働データベースのバックアップを作成し、テスト環境にコピーする方法を示します。 この例では同じサーバー上にありますが、理想的には同じハードウェア容量を持つ別のサーバーにコピーすることをお勧めします。
さらに重要なこととして、実稼働データベースからライブでクエリを記録し、テストスクリプトに追加する方法を示します。 つまり、実稼働データベースからクエリを取得しますが、テストデータベースに対してテストを実行します。
一般的な手順は次のとおりであり、任意のmysqlslapテストに使用できます。
-
1. 実稼働データベースをテスト環境にコピーします。 + *2. 本番データベース上のすべての接続要求とクエリを記録およびキャプチャするようにMySQLを構成します。 + * 3. *テストしようとしているユースケースをシミュレートします。 たとえば、ショッピングカートを実行する場合、アプリケーションから適切なデータベースクエリをすべてトリガーするために何かを購入する必要があります。 + * 4. *クエリログをオフにします。 + * 5. *クエリログを見て、テストするクエリのリストを作成します。 + * 6. *テストするクエリごとにテストファイルを作成します。 + * 7. *テストを実行します。 + * 8. *出力を使用して、データベースのパフォーマンスを改善します。
まず、従業員データベースのバックアップを作成しましょう。 バックアップ用に別のディレクトリを作成します。
sudo mkdir /mysqlslap_tutorial/mysqlbackup
cd /mysqlslap_tutorial/mysqlbackup
バックアップを作成して、新しいディレクトリに移動します。
sudo mysqldump --user sysadmin --password --host localhost employees > ~/employees_backup.sql
sudo cp ~/employees_backup.sql /mysqlslap_tutorial/mysqlbackup/
MySQLテストサーバーに移動します。 データベースを作成します。
CREATE DATABASE employees_backup;
この時点で、テスト用に別のサーバーを使用している場合は、ファイルをそのサーバーにコピーする必要があります。 メインターミナルセッションから、バックアップデータをデータベースにインポートします。
sudo mysql -u sysadmin -p employees_backup < /mysqlslap_tutorial/mysqlbackup/employees_backup.sql
*実稼働MySQLデータベースサーバー*で、MySQLの一般クエリログを有効にし、ファイル名を指定します。 一般的なクエリログは、MySQLデータベースインスタンスの接続、切断、およびクエリアクティビティをキャプチャします。
SET GLOBAL general_log=1, general_log_file='capture_queries.log';
次に、実稼働MySQLサーバーでテストするクエリを実行します。 この例では、コマンドラインからクエリを実行します。 ただし、クエリを直接実行する代わりに、アプリケーションからクエリを生成することもできます。 テストする遅いプロセスまたはWebサイトページがある場合は、そのプロセスを実行するか、そのWebページにアクセスする必要があります。 たとえば、ショッピングカートを実行している場合、ここでチェックアウトプロセスを完了すると、データベースサーバーですべての適切なクエリがトリガーされます。
これは、本番MySQLサーバーで実行するクエリです。 最初に適切なデータベースを使用します。
USE employees;
クエリを実行します。
SELECT e.first_name, e.last_name, d.dept_name, t.title, t.from_date, t.to_date FROM employees e INNER JOIN dept_emp de ON e.emp_no=de.emp_no INNER JOIN departments d ON de.dept_no=d.dept_no INNER JOIN titles t ON e.emp_no=t.emp_no ORDER BY e.first_name, e.last_name, d.dept_name, t.from_date;
期待される出力:
489903 rows in set (4.33 sec)
クエリが完了したら、一般的なログをオフにします。
SET GLOBAL general_log=0;
ログオンしたままにすると、クエリがログに追加され続けるため、テストが難しくなることに注意してください。 そのため、テストを終了した直後にログを無効にしてください。 ログファイルがディレクトリに作成されたことを確認しましょう。
sudo ls -l /var/lib/mysql/capt*
-rw-rw----. 1 mysql mysql 861 Sep 24 15:09 /var/lib/mysql/capture_queries.log
このファイルをMySQLテストディレクトリにコピーしましょう。 テスト用に別のサーバーを使用している場合は、そのサーバーにコピーします。
sudo cp /var/lib/mysql/capture_queries.log /mysqlslap_tutorial/
このログファイルにはかなりの量のデータがあるはずです。 この例では、必要なクエリは終わり近くにある必要があります。 ファイルの最後の部分を確認します。
sudo tail /mysqlslap_tutorial/capture_queries.log
期待される出力:
6294 Query show databases
6294 Query show tables
6294 Field List departments
6294 Field List dept_emp
6294 Field List dept_manager
6294 Field List employees
6294 Field List salaries
6294 Field List titles
140930 15:34:52 6294 Query SELECT e.first_name, e.last_name, d.dept_name, t.title, t.from_date, t.to_date FROM employees e INNER JOIN dept_emp de ON e.emp_no=de.emp_no INNER JOIN departments d ON de.dept_no=d.dept_no INNER JOIN titles t ON e.emp_no=t.emp_no ORDER BY e.first_name, e.last_name, d.dept_name, t.from_date
140930 15:35:06 6294 Query SET GLOBAL general_log=0
このログには、SQLコマンドとそのタイムスタンプが表示されます。 ファイルの終わり近くにあるSQLステートメントは、私たちが興味を持っているものです。 実稼働データベースで実行したコマンドとまったく同じである必要があります。これは、そこで取得したためです。
この例では、クエリをすでに知っています。 ただし、実稼働環境では、このメソッドは、サーバーで実行されているクエリについて必ずしも知っているとは限らないクエリを見つけるのに非常に役立ちます。
ロギング中に異なるクエリを実行またはトリガーした場合、このファイルは完全に異なるように見えることに注意してください。 実際のシナリオでは、このファイルには、さまざまな接続からの何百ものエントリが殺到する可能性があります。 目標は、ボトルネックの原因となっているクエリを見つけることです。 まず、テキストを含むすべての行のリストを作成します。 次に、テスト中にデータベースで実行されたクエリの正確なリストが表示されます。
テストするクエリごとに、拡張子が「+ .sql +」で終わるファイルにコピーします。
例えば:
sudo vi /mysqlslap_tutorial/capture_queries.sql
内容は、テストするMySQLクエリである必要があります。改行はなく、末尾にセミコロンはありません。
SELECT e.first_name, e.last_name, d.dept_name, t.title, t.from_date, t.to_date FROM employees e INNER JOIN dept_emp de ON e.emp_no=de.emp_no INNER JOIN departments d ON de.dept_no=d.dept_no INNER JOIN titles t ON e.emp_no=t.emp_no ORDER BY e.first_name, e.last_name, d.dept_name, t.from_date
次に、クエリ結果がキャッシュされていないことを確認します。 *テストMySQLセッション*に戻ります。 次のコマンドを実行してください。
RESET QUERY CACHE;
次に、スクリプトファイルを使用してmysqlslapユーティリティを実行します。 パラメータで正しいスクリプトファイル名を使用していることを確認してください。 10個の同時接続のみを使用し、テストを2回繰り返します。 これを*テストサーバー*から実行します。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=10 --iterations=2 --create-schema=employees_backup --query="" --verbose
ベンチマークの出力は、システムでは次のようになります。
Benchmark
Average number of seconds to run all queries: 68.692 seconds
Minimum number of seconds to run all queries: 59.301 seconds
Maximum number of seconds to run all queries: 78.084 seconds
Number of clients running queries: 10
Average number of queries per client: 1
それでは、このベンチマークをどのように改善できますか?
クエリの実行内容を評価するには、MySQLクエリにある程度精通している必要があります。
クエリを振り返ると、複数のテーブルで多数の結合が行われていることがわかります。 クエリは従業員の職歴を示し、その際にフィールドごとに異なるテーブルを結合します。 また、参加のためにフィールドを使用していますが、部門の記録は数少ないため、これは無視します。 データベースには多くのエントリがあるため、フィールドにインデックスを作成するとクエリが改善されると想定するのは理にかなっています。
少し練習すれば、サーバーに負荷がかかるクエリ(mysqlslapが役立つ部分です!)を見つけたら、MySQLとデータベースの知識に基づいてクエリに関する評価を行うことができます。
次に、データベースまたはデータベースで実行されているクエリの改善を試みることができます。
この場合、上記のインデックスを追加しましょう。 に3つのインデックスを作成します。 1つのインデックスはテーブルのフィールドに作成され、別のインデックスはテーブルのフィールドに作成され、最後のインデックスはテーブルのフィールドに作成されます。
テストMySQLセッションに移動して、次のコマンドを実行します。
USE employees_backup;
CREATE INDEX employees_empno ON employees(emp_no);
CREATE INDEX dept_emp_empno ON dept_emp(emp_no);
CREATE INDEX titles_empno ON titles(emp_no);
テストサーバーのメインターミナルウィンドウに戻り、同じパラメーターでmysqlslapを実行すると、ベンチマークに違いが見られます。
sudo mysqlslap --user=sysadmin --password --host=localhost --concurrency=10 --iterations=2 --create-schema=employees_backup --query="/mysqlslap_tutorial/capture_queries.sql" --verbose
Benchmark
Average number of seconds to run all queries: 55.869 seconds
Minimum number of seconds to run all queries: 55.706 seconds
Maximum number of seconds to run all queries: 56.033 seconds
Number of clients running queries: 10
Average number of queries per client: 1
クエリを実行するための平均時間、最小時間、および最大時間にすぐに改善があることがわかります。 平均68秒の代わりに、クエリは55秒で実行されます。 同じ負荷で13秒の改善です。
このデータベースの変更はテスト環境で良好な結果をもたらしたため、データベースの変更には通常、長所と短所のトレードオフがあることに留意しながら、本番データベースサーバーへの展開を検討できます。
ログから収集したすべてのクエリで、コマンドのテストと改善のプロセスを繰り返すことができます。
トラブルシューティング-mysqlslapに出力が表示されない
テストコマンドを実行しても出力が得られない場合は、サーバーリソースが最大限に使用されている可能性があります。 症状には、出力の不足、または「+ mysqlslap:結果の保存時のエラー:2013 query +の間にMySQLサーバーへの接続が失われた」などのエラーが含まれる場合があります。
またはパラメータの数値を小さくして、テストを再試行することもできます。 または、テストサーバー環境をアップグレードしてみてください。
これは、データベースサーバーの容量の外側の制限を見つける良い方法です。
結論
mysqlslapはシンプルで軽量なツールで、使いやすく、MySQLデータベースエンジンとネイティブに統合されます。 バージョン5.1.4からMySQLのすべてのエディションで利用できます。
このチュートリアルでは、さまざまなオプションでmysqlslapを使用する方法を見て、サンプルデータベースを試しました。 MySQLサイトから他のサンプルデータベースをダウンロードして、それらを使って練習することもできます。 前述したように、運用データベースサーバーでテストを実行しないでください。
このチュートリアルの最後の使用例では、クエリは1つだけでした。 3つのテーブルすべてに追加のインデックスを追加することで、クエリのパフォーマンスを多少改善しましたが、実際のプロセスはそれほど単純ではないかもしれません。 追加のインデックスを追加すると、システムのパフォーマンスが低下する場合があり、DBAは、追加のインデックスを追加するメリットとパフォーマンスコストを比較検討する必要があります。
実際のテストシナリオはより複雑ですが、これにより、データベースパフォーマンスのテストと改善を開始するためのツールが提供されます。