MySQL 入門

MySQL のバルクインサートとデータ移行

1回のオペレーションで複数行のデータを挿入(インサート)することは、複数の独立した INSERT ステートメントを実行するよりも効率的です。これは、クライアントと MySQL サーバー間の通信オーバーヘッド(Overhead)を削減できるためです。各行に対して個別にコマンドを送信するのではなく、それらを1つのトランザクション(Transaction)にまとめて実行するのがベストプラクティスです。

1. 複数行データのバルクインサート

複数行のレコードを一度に挿入するには、VALUES 句の中にカンマで区切った値のリストを指定するだけです。構文は非常にシンプルです:INSERT INTO table_name (column1, column2) VALUES (val1, val2), (val3, val4), (val5, val6);

ここでは、suppliers(サプライヤー)テーブルにデータを投入するシナリオを考えます。

-- サプライヤーテーブルに3件のレコードをバルクインサート
INSERT INTO suppliers (supplier_name, city, country)
VALUES 
    ('Global Tech Solutions', 'San Francisco', 'USA'),
    ('Mountain Peak Gear', 'Denver', 'USA'),
    ('Alpine Logistics', 'Bern', 'Switzerland');

このコードを実行すると、MySQL は3行すべてのデータを一度に処理します。数百、数千といった大量のデータを挿入する場合、この複数行構文(バルクインサート)を使用することで、個別の INSERT ステートメントを実行するよりも劇的に処理速度が向上します。

2. INSERT INTO ... SELECT を使用したデータ移行

INSERT INTO ... SELECT ステートメントを使用すると、あるテーブルから別のテーブルへデータをコピーできます。これは、ETL(抽出・変換・ロード)プロセスにおけるデータのアーカイブ、バックアップ作成、あるいはテーブル間でのデータ変換を行う際の標準的な手法です。

リテラル(固定値)を使用する標準的な INSERT とは異なり、このメソッドは SELECT クエリの結果セット(Result Set)を取得し、それをターゲットテーブルに直接流し込みます。

-- 'inactive_suppliers'(非アクティブなサプライヤー)テーブルが存在し、
-- カラムが 'suppliers' テーブルと一致すると仮定
INSERT INTO inactive_suppliers (supplier_name, city, country)
SELECT supplier_name, city, country
FROM suppliers
WHERE country = 'Switzerland';

3. INSERT ... SELECT における重要な注意点

この機能を使用する際は、以下の核心的な原則を念頭に置いておく必要があります。

3.1 カラムの整列 (Column Alignment)

SELECT ステートメント内のカラム数は、INSERT ステートメントで指定したカラム数と正確に一致していなければなりません。ターゲットテーブルのすべてのカラムに挿入する場合はカラムリストを省略することも可能ですが、将来的なテーブル構造(スキーマ / Schema)の変更によるエラーを防ぐため、カラム名を明示的に定義することが推奨されます。

3.2 データ型の互換性 (Data Types)

SELECT ステートメントが返すデータの型は、ターゲットのカラムと互換性がなければなりません。MySQL は自動的に型変換(キャスト / Cast)を試みますが、非常に長い文字列をサイズの小さい VARCHAR カラムに挿入しようとすると、操作は失敗します。

3.3 プライマリキーのコンフリクト (Primary Key Conflicts)

ターゲットテーブルに PRIMARY KEY(プライマリキー)や UNIQUE(ユニーク)制約があり、SELECT ステートメントによって生成された値が既にターゲット側に存在する場合、操作全体が失敗します。この場合、INSERT IGNOREON DUPLICATE KEY UPDATE を使用してコンフリクトを適切に処理する必要があります。