MySQLには一時テーブルを利用するのに便利なCREATE TEMPORARY TABLE構文があります。これは利用しているセッション内だけで有効なテーブルを作成し、セッションが閉じたときに自動的にテーブルが削除される構文になります。
今回はCREATE TEMPORARY TABLE構文の挙動を確認していきましょう。なお、一時テーブルはInnoDB, MEMORY, MyISAM, MERGEストレージエンジンで利用可能ですが、今回は前提としてMySQL 8.0.17のInnoDBでの利用となります。
CREATE TEMPORARY TABLEを使って一時テーブルを作成する
一時テーブルを利用するには、CREATE TEMPORARY TABLES
権限を持つユーザーがCREATE TEMPORARY TABLE
構文を実施する必要があります。CREATE TEMPORARY TABLES権限は、一時テーブルの作成や一時テーブルへのデータの挿入、INDEXの追加などの操作を行うのに必要な権限です。
基本的に、通常のCREATE TABLE構文にTEMPORARYをつけて作成することで、一時テーブルを作成することができます。ただしinnodb_strict_modeがONで、ROW_FORMATがCOMPRESSEDを指定した場合は作成することができません。
実際に同一セッション内でしか利用できないかconn1とconn2を利用して確認してみます。
conn1で作成したtmp_t1が、conn2とセッションを作成し直したconn1で利用できないことが確認できました。なお、上記で使用しているCOMMIT RELEASE
は、トランザクションを終了したあと現在のクライアントセッションを切り離します。詳細については公式ドキュメントの13.3.1 START TRANSACTION、COMMIT、および ROLLBACK 構文をご確認ください。
TEMPORARY TABLEで作成したテーブルは、違うセッションであれば名前が同じでも利用することが可能です。実際にt1とt2テーブルからそれぞれ同じ名前のtmpテーブルを作成し、異なる結果になるか確認してみます。
同じtmpテーブルで違う結果が表示されました。
CREATE TEMPORARY TABLEとレプリケーション
一時テーブルはBINLOG_FORMATの値によってスレーブ側での挙動が違います。BINLOG_FORMATがROWまたはMIXEDの場合は、一時テーブル作成のバイナリログが出力されません。そのため、マスターで作成した一時テーブルそのものはスレーブ側では生成されません。ただし、一時テーブルを利用して既存の永続化されたテーブルを更新する場合は、更新データのバイナリログが出力されてレプリケートされます。
一方、BINLOG_FORMAT=STATEMENTのときは一時テーブルの作成もバイナリログに出力し、レプリケーションとして伝搬されます。ただし、一時テーブルがスレーブ側に存在している状態でMySQLをシャットダウンしてしまうと、再び起動した時には一時テーブルが存在していないため、レプリケーションでエラーが発生してしまう恐れがある点に注意が必要です。もし、BINLOG_FORMAT=STATEMENTで一時テーブルを利用している場合はレプリケーションを一度停止し、Slave_open_temp_tables=0であることを確認してからshutdownを行う必要があります。
一時テーブルを利用する時の注意点
利用を開始する前に確認しておいたほうが良い点があります。
一時テーブルの削除はTEMPORARYをつけたほうが良い
CREATE TEMPORARY TABLE構文で作成した一時テーブルはDROP構文で削除することは可能ですが、誤って通常のテーブルを削除する可能性もあるため、DROP TEMPORARY TABLE構文で削除することをおすすめします。
SHOW TABLESコマンドではテーブルは表示されない
作成した一時テーブルはSHOW TABLESコマンドでは確認できません。もし自身のセッションの一時テーブルの存在確認をする場合は、SHOW CREATE TABLE構文で確認することができます。また、INFOMATION_SCHEMAのINNODB_TEMP_TABLE_INFOでアクティブなステータスのテーブルを確認することも可能です。
一時テーブルの名前変更はALTER文で
一時テーブルはRENAME構文を使って名前を変更することができません。もし一時テーブル名の名前を変更したい場合はALTER TABLE <元のテーブル名> RENAME TO <新しいテーブル名>
を使って変更します。
クエリ内で同じ一時テーブルを複数回使えない
違う一時テーブルであれば利用可能ですが、同じ一時テーブルである場合は下記のようなエラーが発生します。一時テーブルを複数回利用する場合は共通テーブル式(WITH句)を用いて利用する必要があります。
その他の細かい注意点に関しては、公式ドキュメントのTEMPORARY Table Problemsをご確認ください。
使い所
一時テーブルは同一セッション内でしか利用できませんが、どういったところで使うとよいのか考えてみましょう。
たとえば、バッチからのレポート算出などの一時集計としての利用には有用です。特に、MySQL 8.0ではWindow関数や共通テーブル式(CTE)が利用可能になったため、集計のための一時利用に使うのは良いかも知れません。事前にテーブルを準備して、都度TRUNCATEを実施する運用も可能ですが、データが事前に入っていたり、バイナリログを出力する分のコストがかかって生成が遅いなどある場合は、一時テーブルの利用を考えてみてはいかがでしょうか。
また、read_only=1なスレーブに対しても、権限があれば一時テーブルを作成できるので、参照用SLAVEのみでの集計等も可能です。ただし、MySQLのバージョンによってはGTIDのバグがあるので注意が必要です。詳細はMySQL Bugsの #85258 をご確認ください。
まとめ
今回は一時テーブルの挙動と制限事項などを確認していきました。同一セッション内でしか利用はできませんが、一時利用としては便利な場面があるかもしれません。もし使えそうな場面に出くわしたら利用を検討してみてください。