MariaDB 10.6.11でテーブル末尾にデフォルト値NULLのフィールドを追加するとtmpテーブルへコピーが発生する理由

2024-04-02

MariaDB 10.6.11でテーブル末尾にデフォルト値NULLのフィールドを追加するとtmpテーブルへコピーが発生する理由

変更点

10.6.11以前では、ALTER TABLEコマンドでテーブルに新しいフィールドを追加する場合、以下の2つの方法がありました。

  1. オンラインDDL:テーブルをロックせずに、新しいフィールドを末尾に追加します。

10.6.11では、デフォルト値NULLのフィールドを追加する場合、オンラインDDLではなくオフラインDDLが常に使用されます。

オフラインDDLを使用する理由は、以下の2つです。

  1. データの一貫性: オンラインDDLでは、新しいフィールドにデフォルト値が設定される前に、データが挿入される可能性があります。これは、データの一貫性に問題を引き起こす可能性があります。
  2. パフォーマンス: オフラインDDLは、テーブル全体をコピーすることで、新しいフィールドを挿入するよりも高速に処理できる場合があります。

tmpテーブルへのコピー

オフラインDDLでは、新しいフィールドを挿入するために、テーブル全体がtmpテーブルへコピーされます。これは、以下の理由によるものです。

  • テーブル構造を変更するには、テーブル全体をロックする必要があります。
  • ロックされたテーブルに直接変更を加えると、パフォーマンスが低下する可能性があります。
  • tmpテーブルを使用することで、元のテーブルをロックせずに、新しいフィールドを挿入することができます。

影響を受ける場合

以下のいずれかに該当する場合、tmpテーブルへのコピーが発生する可能性があります。

  • MariaDB 10.6.11を使用している
  • テーブルにデフォルト値NULLのフィールドを追加する
  • テーブルサイズが大きい

回避策

tmpテーブルへのコピーを回避するには、以下の方法があります。

  • オンラインDDLを使用できないかどうか確認する: オンラインDDLを使用できる場合は、tmpテーブルへのコピーは発生しません。
  • デフォルト値をNULL以外にする: デフォルト値をNULL以外にすることで、オフラインDDLを使用せずに新しいフィールドを追加することができます。
  • MariaDB 10.6.10以前のバージョンを使用する: 10.6.10以前のバージョンでは、tmpテーブルへのコピーは発生しません。

MariaDB 10.6.11でテーブル末尾にデフォルト値NULLのフィールドを追加すると、tmpテーブルへコピーが発生する可能性があります。これは、データの一貫性とパフォーマンスを向上させるための変更によるものです。tmpテーブルへのコピーを回避するには、上記の回避策を検討してください。




-- テーブル作成
CREATE TABLE test (
  id INT NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  PRIMARY KEY (id)
);

-- デフォルト値NULLのフィールドを追加
ALTER TABLE test ADD COLUMN age INT NULL DEFAULT NULL;

-- テーブル内容確認
SELECT * FROM test;

-- tmpテーブルの存在確認
SHOW TABLES LIKE 'test_tmp';
  1. testテーブルが作成されます。
  2. デフォルト値NULLのフィールドagetestテーブルに追加されます。
  3. tmpテーブルtest_tmpが存在することが確認できます。

注意: 上記のコードは、MariaDB 10.6.11以降でのみ動作します。




MariaDB 10.6.11でテーブル末尾にデフォルト値NULLのフィールドを追加する他の方法

オンラインDDLを使用する

条件:

  • 追加するフィールドがデフォルト値NULL以外の場合は、オンラインDDLを使用できます。
  • オンラインDDLは、テーブルをロックせずに新しいフィールドを追加するため、tmpテーブルへのコピーが発生しません。

方法:

ALTER TABLE test ADD COLUMN age INT NOT NULL DEFAULT 18;

注意: デフォルト値をNULLに設定すると、tmpテーブルへのコピーが発生します。

ALTER TABLE test ADD COLUMN age INT NULL DEFAULT NULL;

別のテーブルを作成してデータを移行する

  1. 新しいフィールドを含む新しいテーブルを作成します。
  2. 既存のテーブルのデータを新しいテーブルにコピーします。
  3. 既存のテーブルを削除します。
  4. 新しいテーブルの名前を既存のテーブルの名前に変更します。

:

-- 新しいテーブルを作成
CREATE TABLE test_new (
  id INT NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  age INT NULL DEFAULT NULL,
  PRIMARY KEY (id)
);

-- データをコピー
INSERT INTO test_new (id, name)
SELECT id, name FROM test;

-- 既存のテーブルを削除
DROP TABLE test;

-- 新しいテーブルの名前を変更
RENAME TABLE test_new TO test;

注意: この方法は、データ量が大きい場合、時間がかかる可能性があります。


mariadb


データベースの可用性とスケーラビリティを向上させる: MySQL レプリケーションのすべて

Tungsten は、MySQL レプリケーション用のオープンソースツールキットです。 以下の機能を提供します。主従レプリケーション: データを 1 つのマスターサーバーから複数のスレーブサーバーに複製します。多重マスターレプリケーション: 複数のマスターサーバー間でデータを複製します。...


MariaDB 10で部分テキスト検索を高速化するFULLTEXTインデックスのプログラミング解説

MariaDB 10 は、MyISAM、Aria、InnoDB、Mroonga などのストレージエンジンで、部分テキスト検索を可能にする FULLTEXT インデックスをサポートしています。このガイドでは、MariaDB 10 で FULLTEXT インデックスを作成、使用、および管理する方法を分かりやすく日本語で説明します。...


自己結合クエリを高速化する:MySQLとMariaDBのパフォーマンス最適化ガイド

パフォーマンスを向上させるためのヒント:インデックスの使用:結合条件となるカラムにインデックスを作成します。複合インデックスを検討し、結合条件で頻繁に使用される複数のカラムを結合します。インデックスの統計情報を確認し、インデックスがクエリの実行計画で使用されていることを確認します。...


【MySQL/MariaDB】クエリ結果を小数点にキャストする方法を徹底解説! CAST(), CONVERT(), FORMAT() 関数を使いこなそう

CAST() 関数は、値を別のデータ型に変換するために使用されます。小数点にキャストするには、次のように CAST() 関数に DECIMAL データ型を指定します。precision は、小数点以下の桁数を含めた合計桁数を指定します。scale は、小数点以下の桁数を指定します。...


MySQL/MariaDBで特定の曜日の前々回以降の行を効率的に取得する3つの方法

この方法は、サブクエリを使用して、特定の曜日の前々回の日にちを取得し、その日以降のすべての行を選択します。説明:LAST_DAY(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)):前月の最終日を取得します。...


SQL SQL SQL SQL Amazon で見る



MySQL/MariaDB/InnoDB で ALTER TABLE コマンドを実行中にエラーが発生したらどうすればいい?

ALTER TABLE コマンドを実行中に、エラーが発生した場合、その変更を元に戻すことは可能でしょうか?回答:残念ながら、ALTER TABLE コマンドは、他の DDL コマンドと同様に、実行時に暗黙的にコミットされるため、通常のロールバック操作では元に戻すことができません。