質問

すべて検索可能な 20 以上の列を含むテーブルを持つアプリケーションがあります。これらすべての列のインデックスを構築すると、書き込みクエリが非常に遅くなります。そして、本当に有用なインデックスは、多くの場合、複数の列にまたがる必要があり、必要なインデックスの数が増加します。

ただし、これらの検索の 95% では、検索する必要があるのは行の小さなサブセットだけであり、非常に少ない数 (たとえば 50,000 行) です。

そこで、基本的に次の列を持つ mySQL パーティション テーブルの使用を検討しました。 isActive これが 2 つのパーティションを分割する基準になります。ほとんどの検索クエリは次のように実行されます。 isActive=1. 。ほとんどのクエリは 50,000 行の小さなパーティションに対して実行され、他のインデックスを使用しなくても高速に実行されます。

唯一の問題は、次の行です。 isActive=1 固定されていません。つまり行の日付などの固定されたものには基づいていません。更新する必要があります isActive その行のデータの使用に基づいて。私が理解しているように、それは問題ではありません。データは UPDATE クエリ中にあるパーティションから別のパーティションに移動されるだけです。

私たちには、 PK の上 id ただし行に関しては。これが問題なのかどうかはわかりません。マニュアルには、パーティションは主キーに基づいている必要があることが示唆されているようでした。主キー ID には行が正しいかどうかの根拠がないため、これは大きな問題になります。 isActive.

役に立ちましたか?

解決

私は MySQL の専門家ではありません。私の焦点は Oracle ですが、何年もパーティショニングに取り組んでおり、提案された使用法は非常に適切ではあるものの、主流のパーティションの理解の範囲内ではないことがわかりました。

カーディナリティの低い列のインデックス

インデックスのマージについてはひとまず脇に置きます。アクティブな行が多少分散していて、非アクティブな行の数との比率が 1:20 であるとします。ページ サイズが 8Kb で、ブロックごとに約 20 行が得られるとします。isactive レコードが非常に均等に分布している場合は、ブロックごとにほぼ 1 つ存在することになります。フルテーブルスキャンは、インデックスを使用して同じ行を検索するよりも、テーブル内のすべてのブロック/ページを読み取る方がはるかに高速です。

したがって、均等に分散しているのではなく、集中しているとします。たとえそれらがページの 20% またはページの 10% に集中していても、そのような場合でもテーブル全体のスキャンはインデックスを実行するよりも優れています。

そこで、インデックスのマージを組み込みます。ISactive のインデックスをスキャンした後、テーブルにはアクセスせず、それらの結果を別のインデックスの結果に結合すると、最終的な結果セットの読み取り結果は、たとえばブロックの 5% 未満になります。それなら、はい、isactive のインデックスとインデックスのマージが解決策になる可能性があります。

ここで注意しなければならないのは、MySQL でのインデックス結合の実装には多くの制限があるということです。これがあなたの状況で機能することを確認してください。しかし、検索できるフィールドがさらに 20 個あるとおっしゃいました。したがって、IsActive インデックスを結合するために利用可能な 2 番目のインデックスが存在するように、すべてのインデックスを作成しない場合、インデックスのマージ/結合は使用されません。

カーディナリティの低い列のパーティション化

この列でパーティションを分割すると、IsActive = True のブロックが 5% 含まれ、それらは高密度にパックされます。フル パーティション スキャンにより、アクティブなレコードのリストがすぐに得られ、他のすべての述語をインデックス シークの代わりにフィルターとして適用できるようになります。

でも、そのフラグは変わりますよね。

Oracle には、行の移行を有効にするコマンドがあります。つまり、Is_Active が True から False に変化すると、行が属するパーティションを移動します。これはかなりコストがかかりますが、その列をパーティション化する代わりにインデックスを作成した場合に発生するインデックスのメンテナンスよりも少しだけ多くなります。パーティション化された例。Oracle は最初に更新によって行を変更し、次に削除、そして挿入を実行します。その列にインデックスを付けた場合、行の更新を実行すると、TRUE のインデックス エントリが削除され、False のインデックス エントリが作成されます。

MySQL に行移行がない場合は、それを行うために crud パッケージをプログラムする必要があります。UPDATE_ROW_ISACTIVE(pk IN number) プロシージャ <---- そのようなもの) が削除と挿入を実行します。

コネラックの回答について

並列アクセスはパーティショニングの 1 つの用途であることに私は同意しますが、それが唯一の用途ではありません。しかし、彼が提供するリンクをたどると、ページの一番下にユーザーのコメントが表示されます。

テーブル上の選択性の低いインデックスに注意してください。Index_Merge 最適化が intersect() アルゴリズムで使用されている場合、複雑な AND/OR WHERE 句によりクエリが非常に遅くなるのは確実です。

それはあなたの状況を物語っていると思われるので、そのコメントを素直に受け取ってください。

他のヒント

その多くの「列」のインデックスを作成する場合は、データ構造を再考したい場合があります。たとえば、代わりに各列を行/録音にします。次に、個々のレコードをリンクする「グループID」と「名前」フィールドを持ち、それがどんなデータであるかを示します。次に、すべてのデータに1つのインデックスのみが必要です。

この名前/値ペアのセットアップは、実際には実際にはかなり一般的であり、一部のNOSQLデータベースが基づいているものです。これはあなたが見たいと思うかもしれない何かです。 MongoDBのようなものは、「すべての」データのインデックス作成に最適です。

あなたはこれにパーティションを必要としません - あなたの単なるインデックスです isActive 列で十分です。 MySQLが使用できることに注意してください インデックスマージ 両方のインデックスを使用する操作。

パーティションは、検索を並行して実行できる場合に役立ちます。たとえば、日付ごとにパーティションを使用する場合、5年間の結果を見つけるために5つのパーティションを同時に検索できます。

「テーブル」と「データベース」の説明は、正規化が欠如している典型的な症状です。検索可能な列が 20 個ある「テーブル」は 3NF ではなく、おそらく 1NF でもありません。最善のアドバイスは、最初の原則に戻ってデータを正規化することです。これにより、テーブルがより狭くなり、テーブルごとの行数も減りますが、確かにモート テーブルになります。ただし、結果ではテーブルごと、全体としてインデックスの数も少なくなります。

そして、はるかに高速なデータベース。幅の広い「テーブル」は、あらゆるレベルでパフォーマンスに悪影響を及ぼします。

ここではパーティションは適用されません。問題は解決されません。

アン id PKというのは、 追加 カラム そして インデックス、サロゲート、実際の主キーの代替物 (ただし代替ではありません)。リレーショナル モデリング手法を使用した場合は、それを排除して、少なくとも 19 の検索可能なインデックスに減らすことができます。たとえば、パーティションに関する制限からわかるように、「テーブル」に関する本格的な作業は、サロゲートではなく、実際の PK を中心に行われます。

それについて議論したい場合は、「テーブル」と接続されているすべての「テーブル」の DDL を投稿してください。

コメントへの返信

このテーブルは「電子メール」と考えるのが最も適切ですが、多くの追加フィールド (カテゴリ/部門/優先度/ワークフロー/所有者) があり、すべて適切に正規化されています。非常に多くのタイムスタンプを含む、他にもさまざまな変数があります。

それがまさにフラット ファイルの定義です。 0NF. 。あなたが「正規化」の暗黙の定義を使用していない限り、あなた自身の説明によると、それは次のとおりです。 まったく正規化されていない. 。これは、正規化を開始する前に開始する記事です。

  • クエリに役立つように、インデックスもファットワイドになることは間違いありません。

  • まだ気づいていないかもしれませんが、そのファイルには大量のデータの重複があり、更新異常 (ある行の列を更新すると、他の行の重複した値を更新する必要があります) が発生し、アプリケーションが不必要に複雑になります。

すべてのことを理解する必要があります。 関連した DBMSベンダーが書く 関連した 処理に最適化されたデータベース エンジン 関連した データベース。つまり、非正規化または非正規化された構造ではなく、正規化された構造に対して最適化されています。

学術的な議論に引き込まれるつもりはありません。SO は質疑応答のサイトであり、ディベート サイトではありません。要求に応じて、ファイルと接続されているすべてのファイルの DDL をポストしてください。そうすれば、(a) ある程度の速度が得られ、(b) 20 以上のインデックス (これもこの状態の一般的な症状です) を回避できることは間違いありません。そうすれば、現実世界の特定の問題に対処して解決でき、議論を避けることができます。

第二に、役割が混同されているようです。SO に質問を投稿しているのは問題を抱えたあなたであり、何百ものパフォーマンスの問題を修正して答えているのは私です。定義上、解決策はあなたのドメインの外にあります。そうでなければ、あなたはそれを解決したことになるため、質問を投稿することはありません。したがって、問題を解決する方法を教えても機能しません。それは私をあなたと同じ制限に縛り付けることになり、問題を解決できなくなることになります。

また、私たちのテストから、WHERE 句に含める必要があるテーブルに対して JOIN するテーブルがたくさんあると、クエリが遅くなるだけです。

実際、私はデータベースのチューニングを生業としており、多数の小さなテーブルを結合するほうが高速であることを実証するテストが数百件あります。テストとコーダーのコーディング能力を調べるのは興味深いでしょうが、それは議論を始めることになるのでやめましょう。質問にこだわりましょう。(a) 異議を申し立てられる前に私が述べたことを証明する (b) 本格的なテストの例が必要な場合は、次のとおりです。 一例 これは完全に文書化されており、Oracle 界の有力者による精査を受け、対応するテストも行われています。

あなたもこれに興味があるかもしれません 質疑応答, 、あなたが近づいているのと同じ議論を殺しました。

結合には費用はかかりません。の ファイル あなたはそれに参加します。そしてレコード数 参加しました どちらの側にも。の 使いやすさ インデックスのコストはそこにあります。それが別の非正規化ファイル (太くて幅が広く、オプションの列が多い) の場合は、確実に遅くなります。

とにかく、投稿された問題を修正することに本当に興味がある場合は、すべての DDL を投稿してください。そうすれば、処理を迅速化できます。パーティションに関して「はい/いいえ」の答えだけが必要な場合 (原因となる問題には対処しない場合)、それでも問題ありません。あなたはすでにそれを持っています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top