MySQLでは一般的に、ユーザーからのクエリやDDLなどの操作はシングルスレッドで処理されます。現行のMySQLでは、PostgreSQLやOracle Databaseが提供しているようなパラレルクエリはサポートしていません。しかし、MySQL 8.
今回は、パラレル操作と関連するパラメーターについて紹介したいと思います。なお、利用しているMySQLのバージョンは、8.
パラレル読み取り
MySQL 8.innodb_
が追加されました。このオプションは、InnoDBのクラスタインデックスのページを同時に読み取るスレッドの数を指定します。セカンダリインデックスの読み取りには適用されません。デフォルトは4で、4つスレッドを利用しパラレル読み取りを実行します。
パラレル読み取りは、以下のステートメントで利用されます。
CHECK TABLE
ステートメント- WHERE句などの条件指定のない
SELECT COUNT(*)
ステートメント
パラレル読み取りの実行中は、専用のスレッドが起動されます。performance_
テーブルからパラレル読み取り用スレッドthread/
)
それでは、例としてSELECT COUNT(*)
ステートメントを実行してみましょう。
mysql> SET innodb_parallel_read_threads=4; Query OK, 0 rows affected (0.00 sec) mysql> SELECT COUNT(*) FROM t0 ; +----------+ | count(*) | +----------+ | 12582912 | +----------+ 1 row in set (1.42 sec)
このステートメント実行中にperformance_
テーブルを確認すると、パラレル読み取り用スレッドthread/
)
mysql> SELECT THREAD_ID,NAME,PROCESSLIST_STATE,PROCESSLIST_INFO FROM performance_schema.threads WHERE NAME IN ('thread/sql/one_connection' , 'thread/innodb/parallel_read_thread') AND thread_id != PS_CURRENT_THREAD_ID(); +-----------+------------------------------------+-------------------+-------------------------+ | THREAD_ID | NAME | PROCESSLIST_STATE | PROCESSLIST_INFO | +-----------+------------------------------------+-------------------+-------------------------+ | 568 | thread/sql/one_connection | executing | SELECT COUNT(*) FROM t0 | | 1258 | thread/innodb/parallel_read_thread | NULL | NULL | | 1259 | thread/innodb/parallel_read_thread | NULL | NULL | | 1260 | thread/innodb/parallel_read_thread | NULL | NULL | | 1261 | thread/innodb/parallel_read_thread | NULL | NULL | +-----------+------------------------------------+-------------------+-------------------------+
innodb_
を1にすると、パラレル読み取り用スレッドは起動しません。
mysql> SET innodb_parallel_read_threads=1; Query OK, 0 rows affected (0.00 sec) mysql> SELECT COUNT(*) FROM t0 ; +----------+ | count(*) | +----------+ | 12582912 | +----------+ 1 row in set (4.09 sec)
mysql> SELECT THREAD_ID,NAME,PROCESSLIST_STATE,PROCESSLIST_INFO FROM performance_schema.threads WHERE NAME IN ('thread/sql/one_connection' , 'thread/innodb/parallel_read_thread') AND thread_id != PS_CURRENT_THREAD_ID(); +-----------+---------------------------+-------------------+-------------------------+ | THREAD_ID | NAME | PROCESSLIST_STATE | PROCESSLIST_INFO | +-----------+---------------------------+-------------------+-------------------------+ | 568 | thread/sql/one_connection | executing | SELECT COUNT(*) FROM t0 | +-----------+---------------------------+-------------------+-------------------------+
実行時間も、パラレル読み取りスレッドが1の場合と4の場合を比較すると、4の方が速くなっていることがわかります。また8.
パラレルインデックス作成
MySQL 8.innodb_
が追加されました。このオプションは、セカンダリインデックスの作成時のソートと、ソート済みデータのロードステージに対するスレッドの最大数を指定します。デフォルトは4で、最大4つのスレッドまで利用します。パラレルインデックス作成中は、performance_thread/
)
インデックス作成には、主に以下のようなステージを処理していきます。
順番 | 処理 | ステージ名 |
---|---|---|
1 | クラスターインデックスの読み取りと一時ソートファイルへのデータの書き込み | alter table (read PK and internal sort) |
2 | データのソート | alter table (merge sort) |
3 | 一時ソートファイルからセカンダリインデックスへソート済みデータのロード | alter table (insert) |
4 | ALTER TABLEステートメントの実行中に実行されたDMLの適用 | alter table (log apply index) |
5 | ALTER TABLEステートメントの終了処理 | alter table (end) |
パラレルインデックス作成は、前述のオプションinnodb_
とオプションinnodb_
を利用して実行しています。
alter table (read PK and internal sort)
ステージでオプションinnodb_
のパラレル読み取りを利用し、alter table (merge sort)
とalter table (insert)
ステージでオプションinnodb_
を利用することでインデックス作成を高速化しています。
たとえば、以下のインデックスを追加するステートメントを流してみます。
mysql> ALTER TABLE t0 ADD KEY idx_col1(col1); Query OK, 0 rows affected (36.56 sec) Records: 0 Duplicates: 0 Warnings: 0
インデックス作成中に、performance_
テーブルを数回SELECTした結果が以下になります。
インデックス作成の初期にalter table (read PK and internal sort)
ステージでthread/
が起動され、パラレル読み取りが動作しているのがわかります。その後、thread/
は閉じられます。次にalter table (merge sort)
とalter table (insert)
ステージでthread/
が起動され、動作してることがわかります。
このように、セカンダリインデックスの作成の特定のステージはパラレルで動作するようになりました。
注意点として、以下のようなセカンダリインデックス作成においてはパラレル操作がサポートされていません。
- 仮想列へのインデックス作成
- フルテキストインデックス作成
- 空間インデックス作成
まとめ
MySQL 8.
今回紹介した内容をもっと詳しく知りたい方は、以下のドキュメントをご確認ください。