私がこれを正しく行っているかどうかを知りたいだけです。私はすでに何時間もグーグルを検索してきましたが、正しい答えが見つかりません。
非常に大量の挿入と更新が含まれる可能性のあるテーブルがあります。行が更新されるたびに、「変更」列が変更されます。私のアプリケーションは、(いくつかの結合とフィルタリングとともに)このテーブルをクエリし、その「変更された」列でソートされたページ付けされた結果を取得する必要があります。私が読んだすべてのことから、ソートに使用される列にインデックスを付ける必要があることがわかります。しかし、頻繁に更新される列にインデックスを付けることは悪い考えであると多くの記事を読んだことがあります。インデックス付きの列の値が変更されるたびにインデックスを再構築する必要があるためです。
それで、これを行う適切な方法は何ですか? 「変更された」列にインデックスを付けると、後でインデックスが非常に大きくなり、常に何度も自分自身を再構築する必要があるときに問題が発生しますか? 「変更された」列にインデックスを付けないと、ページネーションクエリが最終的に遅くなり、アプリケーションが使用できなくなりますか?または、私が考えていない別の解決策はありますか?
-EDIT-私は列のインデックスを使用することに傾いています。しかし、まだ確信が持てないのは、インデックス付けされた列に対する多数のUPDATEが、そのインデックスを使用するSELECTクエリに及ぼす影響です。インデックスによってUPDATEとINSERTの速度が低下することはわかっていますが、インデックスの再構築によるI/Oワークロードの増加(行が更新されるたびに、何十回も発生する可能性がある)かどうかはわかりません。一般的にサーバーのパフォーマンスへの主要なボトルネックになります。それとも、私が考えているほどのボトルネックではありませんか?
INSERTは、UPDATEよりも影響を受けるインデックスへの影響が少ないですが、INSERTはすべてのインデックスに影響します(条件を満たさない条件付きインデックスを除く)。
データを頻繁かつ迅速に取得する必要がある場合は、インデックスが必要です。一方(更新/挿入のインデックス)または他方(フルスキャン検索)の影響を比較検討する必要があります。両方の方法を使用することはできません。妥協点は、データウェアハウジングです。これにより、高速な挿入/更新、まれなフルスキャン(データウェアハウスへのコピー)、最新でないデータの高速検索が可能になります。
(InnoDBを想定...)
データとPRIMARY KEY
は1つのBTreeにあります。各セカンダリINDEX
(UNIQUE
インデックスを含む)は、個別のBTreeにあります。
更新には、データBTreeのレコードを変更する必要があります。 anyインデックスにある列を更新する必要がある場合、事実上、そのBTreeからのDELETE
と、同じBTreeの他のどこかにINSERT
が必要です。
一方で、DELETE
とINSERT
は効率的であるように設計されており、私たちは常にそれを行っています。一方、インデックス付きの列を変更することは、内部では多くの作業であることがわかります。
結論:SELECT
効率とUPDATE
コストの間のトレードオフです。 (あなたは私たちに単純なイエス/ノーを与えるのに十分な情報を提供していません。)
(もっと)
BTreeの1つのスポットから行を削除し、(おそらく)別のブロックに新しい行を挿入した後、ブロックを分割する必要がある場合などがあります。ただし、最悪の場合でも、再調整でインデックス全体を再生成する必要はありません。私はそれがLogNの小さな倍数に制限されていると思います-たとえば、ルートノードまでの各レベルで1つのブロック分割を行う必要があるまれなケースです。 10億行には5つのレベルしかない場合があるため、大きなオーバーヘッドについては触れていません。
さらに、非UNIQUE
インデックスの場合、インデックスの更新は「変更バッファー」にバッファーされます。これはインデックスの更新を収集します。後でディスクに効率的に保存するために、それらは一緒に「バッチ処理」されます。一方、インデックスが必要な場合、システムは変更バッファーと実際のディスク上の(ただしbuffer_poolにキャッシュされている)インデックスの両方を調べます。変更バッファーは、buffer_poolのパーセンテージとして割り当てられます(cfinnodb_change_buffer_max_size
、これは通常25のままです)。
確かにREAD UNCOMMITED
は 災害のレシピ ? 「ダーティーリード」とは呼ばれません。
オラクルについて私が今まで読んだすべてがそう言っています。特に、Tom Kyteの「Oracleデータベースアーキテクチャ」は、Oracleがそのレベルを提供することを拒否し、それは良いことだと述べています。
私はこの投稿でMySQLタグを見ましたが、これは一般的なIMHOのデータベースに広く適用されます。
もちろん、インデックスはINSERT
sとUPDATE
sを遅くします。また、当然、これらはSELECT
sを高速化します。
どちらの場合も、広範な経験やテストを除いて、パフォーマンスが影響を受けるかどうかはわかりません。これをどうするかはビジネス決定であり、技術的決定ではありません。
あなたの質問は、はるかに多くの情報なしでは合理的に答えることができません。 UPDATE
クエリ? SELECT
クエリ?取引レートは?あなたのディスク設定? iostat
の結果はいかがですか? sar
の統計全体?システムがハミングしていますか、それともボトルネック/スローダウンが発生していますか?
あなたの予算はどうですか?レポートの遅延はどれくらい許容できますか?あなたの場合の私の最初の本能は、24時間のラグのあるオフラインのデータウェアハウスソリューションを採用することです(DWは一晩で構築され、なんらかの形のレプリケーションを使用します)。
これは、OLAPレポートが実行中のOLTPシステムを妨害する可能性があることを示しています。ただし、これ以上の情報がなければ明確に言うことはできません。