0

エントリの更新と同じように列の並べ替えとフィルタリングを処理できる高速データベーススキーマを設計したいと思います。

このために、次のシナリオを作成しました。

  • イベントには、名前、ステータス、最終サブスクリプション日、説明、場所が1つだけあります。
  • イベントの空席数はイベントとともに保存され、参加者がサブスクライブするたびに更新されます
  • すべてのイベントには1つのカテゴリがあります
  • イベントはカテゴリ別にのみ一覧表示できます
  • イベントは、名前、ステータス、または日付でフィルタリングできます(xorなし)
  • イベントは、名前、ステータス、または日付で並べ替えることができます(xor)
  • テーブルは10を超えるmioエントリを処理する必要があります

すべてのテストで、MySQLテーブルとInnoDBテーブルを使用しました。また、できるだけ頻繁に複数の挿入/更新/削除を使用しようとしました。フィルタリングは、LIKE'%[word]%'を使用して行われます。

最初に、2つのテーブルを使用しようとしました。1つはカテゴリ用、もう1つはイベント用です。インデックスは、category-name、category-status-name、category-date-name、category-date-status-nameでした。このため、リスト、フィルタリング、および並べ替えは非常に高速でしたが、エントリの挿入、更新、または削除は非常に低速でした。インデックスの再構築に時間がかかりすぎたため、ロックタイムアウトも発生しました。

2番目の試みは、カテゴリ、イベント、場所の3つのテーブルを用意することでした。ただし、ロケーションテーブルに6 mio以上のエントリが含まれている場合も、速度が低下します。速い漁獲量の指標があるからだと思います。10万エントリの追加には約272秒かかります。場所のインデックスは、primary- indexidzip-streetでした。

次の試みは、last-subscription-dateとカウンター用の独自のテーブルを作成することです。しかし、この日付をフィルタリングしたり、これを並べ替えたりする可能性についてはどうでしょうか。

カテゴリ名、カテゴリ日付、カテゴリステータスのような3つのインデックスがある方が良いですか、それとも4つのインデックスカテゴリ名、カテゴリステータス名、カテゴリ日付名、カテゴリ日付ステータスのソリューションです。 MySQLに適した名前を付けますか?

フィールドタイプについても考えています。現在、名前にVARCHARを使用しています。ただし、すべてのエントリの長さが同じであるため、可変長を使用するよりもインデックス内の特定の位置にジャンプする方が高速であるため、CHARの方が適している可能性があります。どう思いますか?

上記のシナリオをサポートする、優れた高速データベーススキーマを設計するためのヒントがありますか?

4

1 に答える 1

1

インデックスは固定長であるため、CHARとVARCHARはインデックスには関係ありませんが、テーブルスキャンには関係します。

私は、具体的なことなしに他の決定的な答えを提供することはできないと思います。私はあなたにいくつかの一般的なアドバイスを与えることができます。

クラスター化インデックス(InnoDB主キーまたは最初の一意キー)への挿入は避けてください。クラスター化インデックスは、自動インクリメント列で使用されることが多く、インデックスは追加されるだけで、中央には何も挿入されません。これにより、インデックスを再構築する必要がなくなります。

非クラスター化(セカンダリ)インデックスの場合、インデックスが大きいほど、挿入時に再構築する必要がある頻度が高くなります。ページがいっぱいになるまで挿入を実行してから、ページを再構築できます。繰り返しますが、インデックスの最後に追加することは問題ありません。

インデックスは削除のマークが付けられているだけであり、アイドル時間中にインデックスが再構築されるため、削除はパフォーマンスに影響しません。

MySQLはインデックスを使用しないため、カーディナリティの低い列にインデックスを作成しないでください。インデックスは必要な場合にのみ追加する必要があります。ここでは、毎回長所と短所を比較検討します。

複数列のインデックスは大きく(ページに収まるエントリが少ない)、より多くのエントリを更新する必要があります。複数列のインデックスは控えめに追加してください。

MyISAMは頻繁な読み取りに適していますが、ロックの競合(テーブルロック)が原因で、マルチユーザー環境で頻繁に更新/挿入が行われなくなります。InnoDBは、ロックの競合(行ロック)が少ないため、マルチユーザー環境での更新に適していますが、読み取りには時間がかかります(行ロックが必要です)。

フォームのフィルタリングではLIKE '%[word]%'インデックスを使用できませんが、フィルタリングではインデックスLIKE '[word]%'を使用できます。

頻繁に更新されるシステムでは、インデックスは、レコードを読み取るためと同様に、更新するレコードを選択するためにも重要です。インデックスが優れているほど、ロックの競合が少なくなり、パフォーマンスが向上し、デッドロックが少なくなります。

JOINが多いほど、コストが高くなり、クエリが遅くなります。JOINは悪くありませんが、多くの行(大きな結果セット)のJOINは遅くなる可能性があります。

パフォーマンスに関連しないいくつかの警告:

InnoDBを使用すると、デッドロックが原因で失敗したトランザクションを処理できるように準備する必要があります。

于 2012-05-30T17:59:38.563 に答える