MySQL学習記録: KEYパーティションが引き起こした血なまぐさい事件

MySQL学習記録: KEYパーティションが引き起こした血なまぐさい事件

需要背景

ビジネス テーブル tb_image のデータの一部は次のとおりです。id は一意ですが、image_no は一意ではありません。 image_no は各ファイルの番号を表します。各ファイルはビジネス システムで複数のファイルを生成します。各ファイルの一意の ID はフィールド id です。

ビジネス テーブル tb_image に関する情報は次のとおりです。

  • image_no によるクエリと id によるクエリ。
  • 在庫データ 2kw;
  • 毎日の成長は約4週間です。
  • 1 日のクエリ量は約 200,000 件です。
  • これは非 ToC システムなので、同時実行の上限がわかります。

ソリューションの選択

上記の業務分析に基づくと、データベースとテーブルを分離する必要はまったくありません。単一のデータベースがシャーディングされている場合、クエリは image_no と id に基づいて実行する必要があるため、1 つの解決策は冗長シャーディングを使用することです (つまり、データの 1 つのコピーは image_no をシャーディング キーとして保存し、データのもう 1 つのコピーは id をシャーディング キーとして保存します)。もう 1 つの解決策は、image_no のみをシャーディング キーとして使用し、id のクエリ要件に基づいて、ビジネス レイヤーが結果をマージするか、サードパーティのミドルウェアを導入することです。

単一のデータベースをテーブルに分割するのはより複雑であることを考慮して、パーティション機能を使用することにしました。さらに、128 個のパーティション (各パーティションには kW レベルのデータ ボリュームがあります) を備えた容量評価パーティション テーブル ソリューションにより、少なくとも 15 年間はビジネスが安定して実行されることが完全に保証されます (図のオレンジ色の部分は、実際のビジネスの成長とより一致しています)。

さらに、RANGE、LIST、および HASH パーティションは VARCHAR 列をサポートしていないため、KEY パーティションを使用することが決定されています。その原理の公式な導入は、MySQL 組み込みのハッシュ アルゴリズムを使用し、パーティション番号の係数を取ることです。

パフォーマンステスト

シャード キーを image_no として選択し、パーティション数を 128 に決定したら、実現可能性とパフォーマンスのテストのためにデータをロードします。パーティション数を 128 に選択した理由は、11 億 / 1kw = 110 ≈ 128 です。また、プログラマーは 2 の累乗を使用することを好みます。しかし、パーティション番号 128 からすべての悪夢が始まります。

128 個のパーティションに 100,000 個のデータを挿入しようとしました。挿入後、驚くべき現象が発生しました。すべての奇数パーティション (p1、p3、p5、…、p2n-1) にデータがありませんでした。同時に、偶数パーティションには大量のデータがあり、あまり均等ではありませんでした。次の図に示すように:

注意: 奇数パーティションの ibd ファイル サイズは 112k です。これはパーティション テーブルを作成するときの初期化サイズです。実際にはデータはありません。これは SQL で確認できます: select partition_name, partition_expression, table_rows from information_schema.partitions where table_schema = schema() and table_name='image_subpart' ;、結果の一部を次の図に示します。

問題を説明するには 10 万個のデータで十分ではないでしょうか?平均すると、各パーティションには約 800 個のデータが含まれています。さて、思い切ったことをしてみましょう。さらに 990w のデータを挿入して、合計 1kw のデータにします。結果は同じで、奇数パーティションにはデータがなく、偶数パーティションにはパーティションがあります。

考えるべき質問

KEY パーティショニングの原理を思い出してみましょう。MySQL に組み込まれているハッシュ アルゴリズムを使用してシャード キーのハッシュ値を計算し、パーティション番号の係数を取得します。この原則は、MySQL の公式 Web サイトにも記載されています。リンクをクリックしてください: 22.2.5 KEY パーティショニング: https://dev.mysql.com/doc/refman/5.7/en/partitioning-key.html。元のテキストは次のとおりです:

キーによるパーティショニングはハッシュによるパーティショニングに似ていますが、ハッシュ パーティショニングではユーザー定義の式が使用されるのに対し、キー パーティショニングのハッシュ関数は MySQL サーバーによって提供される点が異なります。NDB Cluster はこの目的で MD5() を使用します。他のストレージ エンジンを使用するテーブルの場合、サーバーは PASSWORD() と同じアルゴリズムに基づく独自の内部ハッシュ関数を使用します。

**この世にそんなひどいハッシュアルゴリズムがあるはずがないですよね? **どんなアルゴリズムを書いても、そんなに不均一にはならないですよね?現時点では、何らかの設定が原因となっているのではないかと思います。しかし、show variables にはパーティション関連の変数はありません。

その時、一万頭の馬が駆け抜けていった。ドキュメントとソースコードが同期していない可能性がありますか?さて、MySQL のソースコードを見てみましょう。結局のところ、ソースコードが真実に最も近いのです。 KEY パーティションに関連するソース コードは、sql_partition.cc ファイルにあります。著者は、以下に示すように、いくつかのキー ソース コードを傍受しました。一見すると、何も問題はありません。まず、パーティション フィールドのハッシュ値を計算し、次にパーティション番号の係数を取得します。

/**
 (SUB)PARTITION BY KEYのpart_idを計算する
 @param ファイル ストレージエンジンへのハンドラ
 @param field_array PARTTION KEYのフィールドの配列
 @param num_parts KEYパーティションの数
 @param func_value[out] 計算されたハッシュ値を返す
 @return 計算されたパーティションID
*/
列をなして
静的 uint32 get_part_id_key(ハンドラー *ファイル、
               フィールド **field_array、
               uint num_parts、
               long long *func_value)
{
 DBUG_ENTER("パーツIDキーを取得");
 // パーティション フィールドのハッシュ値を計算します *func_value = file->calculate_key_hash_value(field_array);
 // パーティション数を法とする DBUG_RETURN((uint32) (*func_value % num_parts));
}

絶望して、検索エンジンで「不均一なKEYパーティションデータ」を検索してください。検索結果のCSDNフォーラム(https://bbs.csdn.net/topics/390857704)に、民俗学者のHua Xia Xiao Zu氏が次のように答えています。

同僚がパスワード機能を分析して測定したところ、キー分割の場合、各パーティションにデータが含まれるようにするには、パーティションの数を素数としてのみ指定できることが分かりました。 11 パーティションから 17 パーティションまでテストしました。 パーティション 11、13、および 17 のデータのみが基本的に均等に分散されます。

その時、さらに一万頭の馬が駆け抜けていった。しかし、一体何事かと不思議に思いながらも、解決策を見つけたかもしれないと少し興奮していました (MySQL の組み込みハッシュ アルゴリズムがなぜこのように動作するのかは、まだわかりませんが)。最終的に、KEY パーティションを再度テストし、次のように結論付けました。

  1. パーティション番号を 40、64、128 (PARTITIONS 64) などの偶数に設定すると、奇数パーティション (p1、p3、p5、p7、… p2n-1) にデータを挿入できなくなります。
  2. パーティション数を 63 や 121 などの奇数で素数でない数に設定すると (PARTITIONS 63)、すべてのパーティションにデータが含まれますが、不均等になります。
  3. パーティションの数を 137 や 31 (PARTITIONS 137) などの素数に設定すると、すべてのパーティションにデータが格納され、非常に均等に間隔が空けられます。

下の図に示すように、これは著者がパーティションの数を 127 に調整し、100 万のデータを挿入した後の状況です。SQL は、各パーティションのデータ量がほぼ同じであることを証明しています。

まとめ

MySQL の KEY パーティションの使用に伴う大きな落とし穴について公式な説明がないことを知ってショックを受けました。さらに、MySQLのバグがあります: バグ#72428 KEY()によるパーティション分割により、データの分散が不均一になります

この記事を読んで強い関心を持っている学生は、この問題についてさらに深く掘り下げてみることができます。著者は、MySQL ソース コードを詳しく調べて、ハッシュ アルゴリズムの実装がパーティションの数に非常に敏感である理由を調べる時間も設ける予定です。

これで、MySQL学習記録のKEYパーティションによって引き起こされた血なまぐさい事件に関するこの記事は終わりです。MySQL KEYパーティション血なまぐさい事件に関するより関連のある内容については、123WORDPRESS.COMの以前の記事を検索するか、以下の関連記事を引き続き閲覧してください。皆様、今後とも123WORDPRESS.COMを応援してください。

以下もご興味があるかもしれません:
  • MySQL シャーディング入門ガイド
  • PythonはMySQLのパーティションの自動追加と削除を実装します
  • MySql テーブル、データベース、シャーディング、パーティショニングの知識の詳細な説明
  • Mysql の一時テーブルとパーティションテーブルの違いの詳細な説明
  • MySQLパーティションテーブルの詳細な説明
  • MySQL ベストプラクティス: パーティションテーブルの基本タイプ
  • MySQL パーティションテーブルのベストプラクティスガイド
  • MySql テーブル、データベース、シャーディング、パーティショニングの知識ポイントの紹介
  • MySQLテーブルシャーディングとパーティショニングの具体的な実装方法
  • MySQL パーティションテーブルの正しい使用方法
  • MySQL の高度な機能 - データ テーブル パーティショニングの概念とメカニズムの詳細な説明

<<:  JavaScript の手ぶれ補正とスロットリングの説明

>>:  さまざまな環境での Docker Compose のインストール方法

推薦する

mysql8.0.12 でルートパスワードをリセットする方法

データベースをインストールした後、誤ってインストール ウィンドウを閉じたり、長期間 root ユーザ...

Dockerコンテナを外部IPとポートにバインドする方法

Docker を使用すると、外部からコンテナにアクセスしたり、コンテナを相互接続したりすることで、ネ...

MySQL 5.7.18 Green Edition のダウンロードとインストールのチュートリアル

この記事では、MySQL 5.7.18のグリーンバージョンをダウンロードしてインストールする詳細な手...

MySQLのパラメータについてお話しましょう

序文:以前の記事では、特定のパラメータの機能についてよく紹介してきました。しかし、MySQL パラメ...

SQLの最適化では間違いがよく起こります。それはMySQLのExplain Planの使い方を理解していないからです。

目次1. 準備2. 説明計画の概要3. フィールドの詳細な説明4. パーティションクエリにはパーティ...

mysqlは、現在の時刻が開始時刻と終了時刻の間にあるかどうかを判断し、開始時刻と終了時刻が空であることが許可されます。

目次要件: 進行中のアクティビティ データを照会する次のSQLクエリは、上記の4つの要件を満たし、タ...

CSSファイルをインポートする3つの方法の詳細な説明

CSS を導入する方法には、インライン スタイル、内部スタイル シート、外部スタイル シートの 3 ...

HTMLはシンプルで美しいログインページを作成します

まずは見てみましょう。 HTML ソースコード: XML/HTML コードコンテンツをクリップボード...

15行のCSSコードがAppleデバイスをクラッシュさせる可能性があり、最新のiOS 12も例外ではない

たった15行のCSSでiPhoneがクラッシュするWire のセキュリティ研究者 Sabri Had...

JavaScript を使用してページ要素のオフセットを取得/計算する方法

質問コントロールをクリックすると、コントロールの下にフローティング レイヤーが表示されます。通常の方...

LinuxシステムのAnsible自動運用保守導入方法

Ansible は、Python をベースに開発された新しい自動運用・保守ツールです。 多くの古い運...

Excelアップロード機能を実現するVue + iViewの完全コード

1. HTML部分 <Col span="2">ファイルをアップロー...

JavaScriptオブジェクトをマージするさまざまな方法の詳細な説明

目次オブジェクトをマージするさまざまな方法(インターフェースを通じてデータを取得し、それをローカル ...

JavaScript におけるシリアル操作と並列操作

目次1. はじめに2. es5メソッド3. 非同期関数のシリアル実行4. 非同期関数の並列実行5. ...

丸い角や鋭い角の代わりに文字を使用することに関する研究経験の共有

1. フォントと文字表示の関係左側と右側の鋭角部分は Songti フォントで表示されます: &l...