sql >> データベース >  >> RDS >> Mysql

MySQLのALTERTABLE:味方か敵か?

    ALTER TABLEステートメントは、MySQLの世界で最も頻繁に使用されるステートメントの1つです。このステートメントを使用すると、テーブルの列を追加、削除、または変更できます。このブログ投稿では、それが何であるか、何をするのか、いつ使用する必要があるのか​​を詳しく調べます。

    ALTER TABLEとは何ですか?

    すでに述べたように、ALTER TABLEステートメントを使用すると、DBAと開発者は、テーブルの列を追加、削除、または変更できます。簡単に言うと、ALTER TABLEはテーブルの構造を変更します。これにより、列の追加、削除、インデックスの追加または削除、列の名前の変更、または列のタイプの変更が可能になります。

    ALTER TABLEをいつどのように使用しますか?

    ALTER TABLEを使用するには、通常、ALTER、CREATE、およびINSERT権限が必要です。テーブルの名前を変更するために必要な権限は、古いテーブルのALTERおよびDROPであり、次に、作成される新しいテーブルのCREATE、ALTER、およびINSERTの権限です。特定のユーザーに必要な権限を割り当てるには、次のクエリを使用できます。

    GRANT ALTER, CREATE, INSERT ON database.* TO 'demo_user';

    データベースをデータベース名に置き換え、特権を特定のテーブルにのみ適用できるようにする場合はワイルドカードをテーブル名に置き換え(ワイルドカードを使用すると、特権はすべてのテーブルに適用可能になります)、demo_userの名前は次のようになります。あなたのユーザー。すべてのデータベースとその中のすべてのテーブルで特権を使用する場合は、データベースをワイルドカードに置き換えるだけです。

    GRANT ALTER, CREATE, INSERT ON *.* TO 'demo_user';

    ALTER TABLEステートメントを実際に使用するには、テーブルの構造を変更するクエリを実行します。ALTERTABLEは、テーブルの列を追加、削除、または変更するために使用されます。クエリでは、列にインデックスを追加するために使用されます。最も頻繁に使用されるクエリの基本的な例を次に示します。

    ALTER TABLE demo_table ADD column_name VARCHAR(255) NOT NULL DEFAULT ‘’; T

    彼のクエリは、列column_nameをテーブルdemo_tableに追加します。クエリの最後にFIRSTを追加して、その列をテーブルの最初の列にします。

    ALTER TABLE demo_table ADD column_2 VARCHAR(255) NOT NULL DEFAULT ‘’ AFTER column_1; T

    彼のクエリは、テーブルdemo_tableの列column_1の後に列column_2を追加します。

    ALTER TABLE demo_table ADD COLUMN column_2 INT GENERATED ALWAYS AS (column_1 + 1) STORED; 

    このクエリは、生成された列をテーブルに追加します。

    ALTER TABLE demo_table DROP COLUMN demo_column; 

    このクエリは、demo_column列をテーブルdemo_tableにドロップします。

    ALTER TABLE demo_table ADD INDEX demo_index(demo_column); 

    このクエリは、demo_tableというテーブルのdemo_columnという列にdemo_indexという名前のインデックス(名前を選択できます)を追加します。

    ALTER TABLE demo_table ADD INDEX (demo_column), ADD UNIQUE (demo_unique); 

    このクエリは、demo_column列にインデックスを追加し、demo_unique列に一意のインデックスを追加します。

    ALTER TABLE demo_table MODIFY column_name VARCHAR(255) CHARACTER SET utf8mb4; 

    このクエリは、特定の列のデフォルトの文字セットを変更します。

    ALTER TABLE demo_table CONVERT TO CHARACTER SET charset_name; 

    このクエリは、テーブルのデフォルトの文字セットとすべての文字(CHAR、VARCHAR、およびTEXT)列を変更します。

    ALTER TABLE demo_table PARTITION BY HASH(demo_column) PARTITIONS 8; 

    このクエリは、列demo_columnをハッシュによって8つのパーティションに分割します。

    ALTER TABLE demo_table TABLESPACE tablespace_1 STORAGE DISK; 

    このクエリは、テーブルdemo_tableをディスクベースのストレージに変換します。

    インデックスを追加する場合は、さまざまなタイプのインデックス(BTREEインデックスやFULLTEXTインデックスなど)を追加できることに注意してください。また、特定の量のみをカバーするインデックスを追加することもできます。次のようなクエリを持つ列の文字の数:

    ALTER TABLE demo_table ADD INDEX demo_index(column_name(10));

    上記のクエリは、demo_tableというテーブルのcolumn_nameという列の最初の10文字にdemo_indexというインデックスを追加します。

    MySQLのインデックスは複雑な獣であり、実際に独自のトピックに値するため、ここでは詳しく説明しませんが、詳細を知りたい場合は、MySQLインデックスに関する以前の投稿でいくつかの情報を提供する必要があります。より多くの洞察。

    ALTER TABLEはどのように機能しますか?

    MySQLのALTERTABLEには独自の微妙な点があります。 MySQLの最新バージョン、つまりMySQL8.0の時点。このような変更に対してALTERTABLEがどのように実行するかに影響を与える3つのアルゴリズムがあります。これらは次のとおりです。

    • コピー

      • 操作は元のテーブルのコピーに対して実行され、テーブルデータは元のテーブルから新しいテーブルに行ごとにコピーされます。ほとんどの場合、このアルゴリズムは、特に大きなテーブルと大きなテーブルの場合、リソース使用量の点で非常にコストがかかる可能性があります。このアルゴリズムが選択または選択された場合、すべての同時DMLは許可されないため、影響を受けるテーブルを参照する後続のクエリは、待機するか、プロセスリストにキューイングされる必要があります。接続が最大になると、データベースがスタックする可能性があります。

    • INPLACE

      • 操作はテーブルデータのコピーを回避しますが、テーブルを所定の位置に再構築する場合があります。テーブルの排他的なメタデータロックは、操作の準備段階と実行段階で短時間取得される場合があります。通常、同時DMLがサポートされています。

    • インスタント

      • 操作は、データディクショナリのメタデータのみを変更します。準備および実行中にテーブルに対して排他的なメタデータロックが取得されることはなく、テーブルデータは影響を受けないため、操作が瞬時に行われます。同時DMLが許可されます。 (MySQL 8.0.12で導入)

    MySQLのALTERTABLEプロセスは、小さいテーブルでは問題にならない可能性がありますが、データセットが大きい場合は、問題が発生する可能性があります。多くの人が、数時間、数日、さらには数週間かかるALTERTABLEクエリを経験しています。完了します。ほとんどの場合、これは、上記で概説したMySQLのテーブル変更プロセスが原因で発生します。ただし、クエリの完了にかかる時間を少なくともわずかに短縮する方法があります。

    1. CREATE TABLE demo_table_new LIKE demo_table;
      次に、その構造を調整します。この場合、demo_tableはソーステーブルであり、demo_table_newは新しいテーブルです。
    2. 新しいテーブルにデータを挿入します。
    3. 古いテーブルの名前をdemo_table_oldに変更します(必要に応じて名前を調整します)。
    4. 新しいテーブルの名前を古いテーブルの以前の名前に変更します。
    5. 最後に、古いテーブルから新しいテーブルに行をコピーし、必要に応じてインデックスを作成します。

    上記の手順は正常に機能しますが。それでも、実際のケースシナリオでは、DBAまたは開発者は、Perconaのpt-online-schema-changeを使用するか、Githubのgh-ostを使用することに傾倒します。これらのスキーマ変更ツールの概要を説明する、以前の投稿「MySQLおよびMariaDB移行用のトップオープンソースツール」をご覧ください。

    とにかく、上記で説明したことは、「シャドウコピー」アプローチとしてよく知られています。基本的に、目的の構造で新しいテーブルを作成し、名前の変更とドロップを実行して2つのテーブルを交換します。 。別の方法もあります。サーバーを交換して、本番環境にないサーバーでALTERTABLEを実行することもできます。 MyISAMの場合、キーを無効にし、データをロードしてから、キーを有効にすることができます。

    代替テーブルの落とし穴

    ALTER TABLEステートメントを使用してインデックスを作成している場合(CREATE INDEXステートメントも使用できます)、データを挿入した後にインデックスを作成することをお勧めします。これは非常によく知られている方法です。 MySQLだけでなく、Oracleなどの他のデータベース管理システムでも処理します。ただし、一般的に、ほとんどのALTER TABLE操作は、MySQLにいくつかの問題(サービスの中断)を引き起こすことが予想されることに注意してください。

    プロセス全体を高速化する別の方法もありますが、少し高度です。MySQLにテーブルの.frmファイルのみを変更するように説得できる場合(.frmファイルは次の定義を記述します)テーブル)、テーブルをそのままにしておくと、プロセスが速くなります:

    1. 古いテーブルと同じレイアウトで、変更せずに空のテーブルを作成します。
    2. 使用中のすべてのテーブルを閉じ、
      FLUSH TABLES WITH READ LOCK.
    3. .frmファイルを交換します。
    4. UNLOCK TABLESを実行して、読み取りロックを解除します。

    また、列を変更したいのに構文が正しいように見えてもエラーが発生する場合は、別の構文を調べる必要があるかもしれないことにも注意してください。例:

    ALTER TABLE demo_table ADD long VARCHAR(255); 

    longは予約語であるため、このようなクエリはエラーになります。このようなエラーを回避するには、バッククォートで単語をエスケープします。

    ALTER TABLE demo_table ADD `long` VARCHAR(255);

    列名は、一重引用符または二重引用符ではなく、バッククォートを使用してのみエスケープできることにも注意してください。たとえば、そのようなクエリでもエラーが発生します:

    ALTER TABLE demo_table CHANGE COLUMN ‘demo_column’ ‘demo_column_2’ VARCHAR(255);
    概要

    MySQLは、ALTER TABLEステートメントを使用して、テーブルの列を追加、削除、または変更します。ステートメントが正常に実行されるためには、テーブルに対するALTER、CREATE、およびINSERT特権が必要です。ステートメントには、それ自体に固有の微妙な点もいくつかあります。非常に大きなテーブルで実行すると、その動作方法が原因でパフォーマンスが低下する可能性がありますが、ステートメントの動作と動作を理解している限り、問題はありません。


    1. @@ ROWCOUNT –SQLServerの最後のステートメントの影響を受ける行数を取得する

    2. listaggデータを使用可能な形式に?

    3. SQL ServerのテーブルからXML値と属性をクエリする方法は?

    4. ビューオラクルで累積合計を作成します