0

既存の MySQL データベースのパフォーマンスを改善しようとしています。

これはレストランに関するデータベースで、関連するテーブルが 2 つあります。

Web サイトのすべてのエンティティのテーブルがあり、すべてのエンティティには一意の ID があり、エンティティはほとんど何でもかまいません。レストラン、ユーザー、その他多くのものです。いくつかのエンティティ タイプがあり、レストランのエンティティ タイプは「オブジェクト」です。

また、データベースのこの構造はほとんど存在しているので、大きな変更はしたくありません。たとえば、すべてのエンティティのテーブルを削除するつもりはありません。(データベース自体にはデータはありませんが、PHP エンジンが組み込まれているため、構造に大きな変更を加えることは困難です)。

オブジェクト専用のテーブルもあります。そのデータベースにはいくつかのタイプのオブジェクトがありますが、特にレストランはウェブサイトの主題であるため、多くの検索が行われます。レストランには国、都市、名前、ジャンルなどのいくつかのフィールドがあります。同じ都市と国に同じ名前のレストランが 2 つ存在することはありません (たとえば、同じ名前で同じ国の異なる都市にある 2 つのレストラン、または同じ名前であるが同じ国にある 2 つの都市に存在する可能性があります)。異なる国)

したがって、この事実から、国、都市、および名前の列に対して一意の 3 列のインデックスを作成する必要があると思います。

また、URL も www.domain.com/Country/City/Restuarant-Name の形式で作成されているため、country-city-name の組み合わせは高速にフェッチされ、このタイプのクエリが発生します。多く。

しかし、他の多くのタイプのクエリもあります: 特定の都市または特定の場所にあるレストランの名前の検索 (検索する名前がフルネームの一部である可能性があるため、LIKE クエリを使用)国。特定の国や都市にある特定のジャンルのすべてのレストランを検索します。そして可能なほとんどすべての組み合わせ。

おそらく最もよく使用されるクエリは、(a) 特定の都市と国のレストラン名を検索すること (URL を入力するときに使用されるクエリと同じですが、LIKE を使用します)、(b) ある場所のレストランを検索することです。特定の都市と国の特定のタイプ。最後に (c) グローバルにレストラン名を検索する (データベース全体で、都市と国を指定せずに)

このテーブル (オブジェクト テーブル) には現在、オブジェクトの ID である PRIMARY KEY があります。ID もよく使用されます。ベスト プラクティスは次のようになりますか?:

  1. 国、都市、名前から 3 列の UNIQUE インデックスを作成する
  2. 名前から別の(一意ではない)インデックスを作成します(そのため、上記で書いたタイプ c のクエリは高速に実行されます)
  3. オブジェクトテーブルからレストランのみを含むサブテーブルを作成して、このサブテーブルがクエリされるようにすることもできます。(これはそれほど重要ではありません。大きな変更を加えることにした場合、最初にオブジェクトの残りの部分からレストランを分離する可能性が高いからです)

長い間これを決定しようとしてきたので、助けていただければ幸いです。

ps オブジェクト テーブルの一部のオブジェクトにはジャンルや国や都市がないため、NULL のままになります。NULL 値が UNIQUE KEY で許可されていることはわかっていますが、パフォーマンスに影響がありますか?

この長い質問を喜んで読んでくれた人に感謝します:)

4

1 に答える 1

1

好きなだけ考えて計画を立てることができますが、オプションを試してベンチマークし、比較するまで、何が最善かはわかりません。そうは言っても、あなたは間違いなく正しい軌道に乗っているように聞こえます.

複合キー
"country-city-name" 複合キーは、最も広い選択基準から最も狭い選択基準の順に並べられているため、最も有用な順序になっているようです。複合キーの値は左から右にしか使用できないため、意図的にこれを行ったと確信しています。nameはそのインデックスの最初に来ないため、指摘したように、 nameだけに別のキーが必要になります。

NULLのインデックス値imysql.cn
に よると、「インデックスで NULL 値を許可しても、実際にはパフォーマンスに影響はありません。」それは単にデータや参照なしで余談として述べられているので、彼らがそれをどのように/または証明したかはわかりません.

テーブルを分割する
レストランのレコードに他のデータがたくさん混ざっている場合は、確かに処理が少し遅くなる可能性があります。テーブルを同じ構造の「レストラン」テーブルと「その他」テーブルに分割しても、必要に応じて単純な UNION を使用して、これらの組み合わせたデータを簡単にクエリできます。予想されるデータ/速度低下についての考えがない限り、少なくとも単純さ/均一性のために、必要な場合を除き、テーブルのシャーディングは避けたいと思います。

国を含まない都市など、現在のインデックス作成では考慮されない予測可能なクエリはありますか? その場合は、予見可能なすべてのケースをカバーするために適切にインデックスを作成してください。あなたはそれについて言及していませんでしたが、ジャンルのインデックスもあると思います。


最終的には、大量のテスト データを生成して試してみる必要があります。(最終的に期待できるデータの量を決定し、少なくともその 3 倍の量のテスト データを生成して、システムをそのペースでテストします。) あなたが説明したことから、設計はかなり良さそうに見えますが、テストによって予期しない問題が明らかになる可能性があります。さまざまなインデックス作成などのメリットがあります。問題が見つかった場合は、すべての仮定のシナリオを単純に熟考するのではなく、特定の目標を達成する必要があります。

于 2011-06-17T19:32:45.400 に答える