MySQL データテーブルのパーティション戦略と利点と欠点の分析

MySQL データテーブルのパーティション戦略と利点と欠点の分析

なぜパーティションが必要なのでしょうか?

巨大なデータ テーブルに直面した場合、少なくとも 1 つのことは確かです。それは、テーブルが非常に大きいため、クエリを実行するたびにテーブル全体をスキャンすることはできないということです。この時点では、インデックスは使用できないか、またはインデックスの重要性がほとんどなく、インデックスのメンテナンスコストと占有スペースが非常に高いことは言うまでもありません。インデックスに依存すると、断片化された低密度のデータが大量に生成され、クエリ中に何千ものランダム I/O アクセスが発生し、ダウンタイムが発生します。この場合、通常は 1 ~ 2 個のインデックスのみが使用され、それ以上は使用されません。この場合、2 つのオプションが考えられます。クエリは、テーブルの指定された部分またはデータの必要な部分から順番に検索する必要があり、そのインデックスはサーバーのメモリと一致する必要があります。

繰り返しになりますが、ストレージ スペースが大きすぎる場合、インデックスがクエリ全体をカバーしない限り、バイナリ ツリー インデックスは機能しません。サーバーはデータ テーブル内のデータの行全体を検索し、大きな領域の範囲でランダム I/O 操作を実行する必要があるため、クエリ応答時間が許容できないほど長くなります。インデックスの維持(ディスク領域、I/O 操作)にもコストがかかります。

これはパーティショニングによって解決できる問題です。ここで重要なのは、パーティショニングはインデックス作成の原始的な形式であり、オーバーヘッドが少なく、近くのデータから結果を取得できることです。この場合、隣接するデータを順番にスキャンするか、隣接するデータをメモリにロードして取得することができます。パーティションの負荷が低い理由は、対応するデータ行へのポインターがなく、更新する必要がないためです。パーティショニングでは、データを正確に行に分割するわけではなく、いわゆるデータ構造も使用されません。実際、パーティショニングはデータの分類と同等です。

パーティショニング戦略

大規模なデータ テーブルの場合、パーティション分割には 2 つの戦略があります。

  • インデックスは使用されません: データ テーブルを作成するときに、インデックスは追加されません。代わりに、パーティションを使用して必要なデータ行が検索されます。 WHERE 条件を使用してクエリを小さなパーティション範囲に分割するだけで十分です。現時点では、クエリ応答時間が許容可能かどうかを計算するには数学的手法が必要です。もちろん、ここでの前提は、データがメモリに格納されず、すべてのデータがディスクから読み取られることです。したがって、データは他のクエリによってすぐに上書きされ、キャッシュを使用する意味がほとんどありません。この状況は、データ テーブルの基数が大きい場合によく発生します。パーティションの数は数百に制限する必要があることに注意してください。
  • インデックスを使用してホット ゾーン データを分離する: ホット ゾーン データ以外のデータのほとんどが使用されない場合は、ホット ゾーン データを個別にパーティション化し、このパーティションとインデックスをメモリにロードできます。このとき、通常のデータ テーブルを操作するのと同じように、インデックスを使用してパフォーマンスを最適化できます。

パーティションの危険性

2 つのパーティション分割戦略は、クエリ中にパーティションをフィルタリングすることで検索範囲を絞り込むことができ、パーティション自体のコストは高くないという 2 つの重要な前提に基づいています。ただし、これら 2 つの仮定は必ずしも有効であるとは限りません。次のような問題が発生する可能性があります。

  • NULL 値によりパーティション フィルタリングが失敗する可能性があります。パーティション関数が NULL になる可能性がある場合、パーティション分割作業の結果は非常に奇妙なものになります。最初のパーティションは特別なものであると想定されます。 PARTITION BY RANGE YEAR(order_date) が使用されていると仮定すると、order_date 列が NULL または無効な日付の場合、最初のパーティションに格納されます。次のクエリ条件を使用してクエリを記述するとします: WHERE order_date BETWEEN '2021-01-01' AND '2021-01-31'。 MySQL は実際には 2 つのパーティションをチェックします。1 つは無効な入力を受け取ったときに NULL を返す可能性がある関数である YEAR 用で、もう 1 つは NULL になる可能性がある適格な値 (最初のパーティションに格納されている) 用です。これは、TO_DAYS などの他の関数でも可能です。最初のパーティションが大きい場合、特にインデックスなしの最初の戦略を使用する場合、問題が発生する可能性があります。 1 つのパーティションではなく 2 つのパーティションからデータを検索する効果はまったく予想外です。これを回避するには、たとえば PARTITION p_nulls VALUES LESS THAN (0) のように、「偽の」最初のパーティションを作成する必要があります。データ テーブルに無効なデータが格納されていない場合、最初のパーティションは空になります。スキャンされますが、空であるか、データが非常に少ないため、パフォーマンスにほとんど影響はありません。 MySQL 5.5 以降では、列を直接パーティション分割に使用する場合はこの状況を処理する必要はありませんが、関数を使用する場合は処理する必要があります。
  • インデックスがパーティションと一致しません: パーティション条件と一致しないインデックスが定義されている場合、クエリはパーティションをフィルター処理できない可能性があります。フィールド a にインデックスが定義されているが、フィールド b がパーティション分割に使用されているとします。各パーティションには独自のインデックスがあるため、このインデックスに対するクエリはすべてのパーティションのインデックス ツリーを走査します。インデックス ツリーのリーフ以外のノードがすべてメモリに格納されている場合、クエリは高速になりますが、インデックス全体のスキャンを回避する方法はありません。この状況を回避するには、WHERE 条件自体でパーティションを指定できない限り、パーティション化されていないインデックス列の使用を避ける必要があります。これは簡単に避けられるように思えますが、実際には驚くべきことです。たとえば、パーティション テーブルが 2 番目のテーブルとの結合クエリで使用され、結合クエリで使用されるインデックスがパーティション インデックスではないとします。次に、ユニオン クエリの各行が 2 番目のテーブルのパーティションにアクセスしてスキャンします。
  • どのパーティションを使用するかを決定するのはコストがかかる可能性があります。パーティション分割はさまざまな方法で実装されるため、実際のパフォーマンスは常に一貫しているとは限りません。特に、「このデータ行はどのパーティションに属しているか」や「クエリ条件に一致するデータ行を見つけるにはどうすればよいか」などの質問に遭遇した場合。パーティションが非常に多い場合、このような質問に答えるのは困難です。線形検索は必ずしも効率的ではなく、結果としてパーティションの数が増えるにつれてコストが高くなります。最悪なのは、行ごとに挿入することです。パーティション化されたデータ テーブルにデータ行が挿入されるたびに、サーバーは新しいデータ行を格納するために使用するパーティションを見つけるために 1 回スキャンする必要があります。この問題はパーティションの数を制限することで軽減できますが、実際には、パーティション数が 100 を超えることは推奨されません。もちろん、キー パーティションやハッシュ パーティションなどの他のパーティション タイプにはこのような制限はありません。
  • パーティションを開いてロックするのもコストがかかる場合があります。パーティション化されたテーブルの副作用の 1 つは、クエリで各パーティションを開いてロックする必要があることです。このプロセスは、パーティションをフィルタリングする前に実行されます。このコストはパーティション タイプとは無関係であり、すべての操作ステートメントに影響します。この効果は、1 行のデータのみをクエリする場合など、データ量が少ないクエリで特に顕著になります。この欠陥は、一度に複数の行を挿入する、LOAD DATA INFILE、一度に範囲別にデータを削除するなど、単一の操作ではなくバッチ操作を実行することで軽減できます。もちろん、パーティションの数を制限することも効果的です。
  • メンテナンス操作にはコストがかかる場合があります。パーティションの作成や削除など、一部のパーティション メンテナンスは短時間で完了します。パーティションの調整などのその他の操作は、テーブルに対する ALTER 操作に少し似ており、ループとデータ行のコピーが必要です。たとえば、パーティションのサイズを変更すると、一時的なパーティションが作成され、データが新しいパーティションに移動されてから、古いパーティションが削除されます。

上で述べたように、パーティショニングは完璧な解決策ではありません。現在のバージョンの MySQL には、他にもいくつかの制約があります。

  • すべてのパーティションは同じストレージ エンジンを使用する必要があります。
  • パーティション関数として使用できる関数または式には、一定の制限があります。
  • 一部のストレージ エンジンはパーティション分割をサポートしていません。
  • MYISAM データ テーブルの場合、LOAD INDEX INTO CACHE は使用できません。
  • MYISAM データ テーブルの場合、パーティション化されたテーブルでは、より多くのオープン ファイル記述子が必要になります。つまり、単一のデータ テーブル キャッシュ エントリが複数のファイル記述子に対応する可能性があります。したがって、基本構成では、サーバー オペレーティング システムの前処理量を超えないようにデータ テーブルのキャッシュが制限され、パーティション テーブルでは実際にこの制限を超える可能性があります。

もちろん、MySQL バージョンの更新と反復により、パーティショニングのサポートはますます向上し、多くのパーティショニングの問題が修正されました。

上記は、MySQL データ テーブルのパーティショニング戦略と長所と短所の分析の詳細な内容です。MySQL データ テーブルのパーティショニング戦略と長所と短所の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • SQLは、隣接する2行のデータに対して加算、減算、乗算、除算の演算を実行します。
  • 列の隣接する2つの行の差を計算するMySQLメソッド
  • MySqlで隣接データを取得する方法

<<:  画像の下部の空白部分の問題を解決する

>>:  ウェブサイトのコンテンツの100~1%はナビゲーションである

推薦する

IDEA は Docker プラグインを使用します (初心者向けチュートリアル)

目次例示する1. Dockerリモートアクセスを有効にする2. Dockerに接続する3. イメージ...

Dockerコンテナでyumを呼び出すときのエラーの解決方法

dockerfile またはコンテナ内で yum を実行すると、エラーが報告され、ソースが見つかりま...

Linux に Python 3.8.1 をインストールするための詳細なチュートリアル

この例では、Linux への Python 3.8 のインストールを例に挙げます。 1. 依存パッケ...

MySQL データベースの最適化: テーブルとデータベースのシャーディング操作の詳細な説明

この記事では、例を使用して、MySQL データベースの最適化のためのテーブルおよびデータベース シャ...

よく使われる3つのMySQLデータ型

MySQL のデータ フィールドのタイプを定義することは、データベースを最適化するために非常に重要で...

非常に詳細な MySQL8.0.22 のインストールと設定のチュートリアル

みなさんこんにちは。今日は、MySQL 8.0.22 のインストールと構成について学習します。注意深...

ネイティブ JavaScript でシンプルな Gobang ゲームを実装する

この記事では、JavaScriptで簡単なGobangゲームを実装するための具体的なコードを参考まで...

JavaScript におけるイベント バブリング メカニズムの詳細な分析

バブリングとは何ですか? DOM イベント フローには、イベント キャプチャ ステージ、ターゲット ...

Linuxのdateコマンドの使用

1. コマンドの紹介date コマンドは、現在の時刻または指定された時刻を指定された形式で表示するた...

HTML における Div と table の違い (あらゆる側面から詳細に説明)

1: 速度と読み込み方法の違いdivとtableの違いは速度ではなく、読み込み方法です。速度はネット...

Windows 10 Home EditionにDockerをインストールする方法を教えます

Redisの本やSpring Cloud Alibabaの本を執筆した際に、一部の分散コンポーネント...

CSS を使用して同じ親タグの左側と右側に 2 つのボタンを配置する方法

この記事では、主に同じ親タグの左側と右側にある 2 つのボタンの CSS レイアウト方法を紹介し、皆...

Hyper-v仮想マシンを使用してCentos7をインストールする

目次導入準備するシステムイメージをダウンロードHyper-Vを有効にする新しい仮想ネットワークスイッ...

MySQL 接続制御プラグインの紹介

目次1. 接続制御プラグイン(connection_control)の紹介1.1 connectio...

Vue で手ぶれ補正を実装するためのサンプルコード

手ぶれ防止: 繰り返しのクリックによるイベントのトリガーを防止まず、揺れとは何でしょうか? 震えるの...