大きなmysqlテーブルにインデックスを追加する


13

テーブルがあります

| base_schedule_line_items | CREATE TABLE base_schedule_line_items
idint(10)unsigned NOT NULL AUTO_INCREMENT、
installmentint(10)unsigned NOT NULL、
on_datedate NOT NULL、
actual_datedate DEFAULT NULL、
payment_typeint(11)NOT NULL、
scheduled_principal_outstandingdecimal(65,0)NOT NULL、
scheduled_principal_duedecimal(65,0) NOT NULL、
scheduled_interest_outstandingdecimal(65,0)NOT NULL、
scheduled_interest_duedecimal(65,0)NOT NULL、
currencyint(11)NOT NULL、
updated_atdatetime NOT NULL DEFAULT '2013-01-06 14:29:16'、
created_atdatetime NOT NULL DEFAULT ' 2013-01-06 14:29:16 '、
loan_base_schedule_idint(10)unsigned NOT NULL、
lending_idint(10)unsigned NOT NULL、
rescheduletinyint(1)DEFAULT' 0 '、
PRIMARY KEY(id)、
KEY index_base_schedule_line_items_loan_base_scheduleloan_base_schedule_id)、KEY index_bslt_spdscheduled_principal_due)、
キーindex_bslt_lendinglending_id)、
KEY index_bslt_actualdateactual_date)、
KEY index_bslt_spsilaloan_base_schedule_idscheduled_principal_duescheduled_interest_dueactual_date)、
KEY index_bslt_ondateon_date)、
KEY index_bslt_oaon_dateactual_date)、
KEY index_bslt_olon_dateloan_base_schedule_id)、
KEY index_bslt_olion_datelending_id
)ENGINE = InnoDBのAUTO_INCREMENT = 30410126 DEFAULT CHARSET = utf8 |

このテーブルには3,000万件のレコードがあります。これにさらに2つのインデックスを追加する必要があり、その追加には数年かかります。

テーブルbase_schedule_line_itemsを変更してインデックスindex_bslt_sla(scheduled_principal_due、actual_date、lending_id)を追加します。
テーブルbase_schedule_line_itemsの変更、インデックスの追加index_bslt_ssla(scheduled_principal_due、scheduled_interest_due、lending_id、actual_date);

以下のクエリを使用して、テーブルのサイズを確認しました

SELECT table_name AS "Tables"、round(((data_length + index_length)/ 1024/1024)、2) "サイズin MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

結果は

base_schedule_line_items | 20111.00

私はこれを単にデータ長を計算し、インデックスの長さを省いた

SELECT table_name AS "Tables"、round(((data_length)/ 1024/1024)、2) "サイズin MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

結果は

base_schedule_line_items | 9497.00

インデックス

KEYのindex_bslt_actualdate(actual_date)、
KEY index_bslt_spsila(loan_base_schedule_id、scheduled_principal_due、scheduled_interest_due、actual_date)、
KEY index_bslt_ondate(on_date)、
KEY index_bslt_oa(on_date、actual_date)、
KEY index_bslt_ol(on_date、loan_base_schedule_id)、
KEY index_bslt_oli(on_date、lending_id)

私によって追加されましたが、私は他のインデックスが追加されたのかどうか、またはどのような目的であるかを確信していません。これはかなり大きなアプリケーションです。選択ステートメントを使用してレポートを抽出するのに役立つため、上記の2つのインデックスを追加する必要がありますが、追加するのは非常に困難です。どんな助けも大歓迎です

回答:


16

大きなテーブルを変更するアクティビティは、段階的に行われます。

  1. テストDBに必要なフィールドとインデックスがある新しいテーブルを作成します(構造のみ)
  2. 既存のテーブルからデータをダンプし、テストDBで新しく作成されたテーブルに同じものをロードします
  3. ダウンタイムを発表します:)
  4. 名前を変更してテーブルを入れ替える- RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;これは1秒未満のアトミック操作です。
  5. 新しく作成されたテーブル(ダンプしてからロードした後に来たレコード)に追加のレコードをロードします。このステップは、ダウンタイムを短縮するために、ステップ3の前に1回行うこともできます。
  6. そしてシステムが帰ってきた

いくつかのメモ:

  1. このように情報スキーマに直接アクセスする必要はありません。使用してみてください SHOW TABLE STATUS from db like 'table_name'
  2. alter tableの速度は、I / O速度と多少関係があります。前回、上記の手順を実行せずに直接変更テーブルを実行したとき、40GB以上のテーブルサイズがあり、約4時間かかりました。20GBのデータに数年かかる場合、古いマシンで作業しています。
  3. またindex_bslt_ondate, index_base_schedule_line_items_loan_base_schedule、他のいくつかのインデックスの左端の列がインデックス付き列としてあるなど、不要なインデックスの削除

これらの手順のいずれかについて説明が必要な場合はお知らせください。

編集:プロセスを自動化する単純なpythonスクリプトhttps://github.com/georgecj11/hotswap_mysql_table.git


10

pt-online-schema-changeなどのツールを使用して、アプリケーションをブロックせずにインデックスを追加できます。基本的なロジックは次のとおりです。

  • 新しいインデックスでテーブルの空のコピーを作成します
  • 既存のテーブルにトリガーを追加して、テーブルにヒットした変更がテーブルのコピーに適用されるようにします*
  • 古いテーブルから新しいテーブルへの行のコピーを開始します
  • コピーが完了したら、テーブルを交換します
  • 古いテーブルをドロップする

*テーブルに既存のトリガーがある場合、ツールは機能しません

スワップとドロップの動作は、ツールに渡されたオプションに基づいて調整できます。

また、外部キーには問題があるため、ツールのドキュメントを読んで、ツールの機能を完全に理解してください。

そしてもちろん、必要に応じて復元できるように、テーブルのバックアップがあることを確認するのが賢明です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.