時期尚早の最適化モードに入る前に、次のクエリ テンプレートを調べると役立つ場合があります。これは、考えられる最適化の有効性を測定するためのベースラインとして使用できます。
SELECT T.Tagid, TagInfo.TagName, COUNT(*)
FROM Items I
JOIN Tags TagInfo ON TagInfo.TagId = T.TagId
JOIN ItemTagMap T ON I.ItemId = T.ItemId
--JOIN ItemTagMap T1 ON I.ItemId = T1.ItemId
WHERE I.ItemId IN
(
SELECT ItemId
FROM Items
WHERE -- Some typical initial search criteria
Title LIKE 'Bug Report%' -- Or some fulltext filter instead...
AND ItemDate > '02/22/2008'
AND Status = 'C'
)
--AND T1.TagId = 'MySql'
GROUP BY T.TagId, TagInfo.TagName
ORDER BY COUNT(*) DESC
サブクエリは「駆動クエリ」、つまりエンドユーザーの最初の基準に対応するものです。(このクエリの詳細については、以下を参照してください。最適化されたフロー全体に複数回必要になる可能性があります)基準。これらは、最初の検索の一部として、または絞り込みによって、ユーザーが特定のタグを選択するときに必要になります。(これらの結合と where 句をサブクエリ内に配置する方が効率的な場合があります。これらについては以下で詳しく説明します)
ディスカッション...
「駆動クエリ」またはそのバリエーションは、2 つの異なる目的で必要です。
1 は、関連するすべてのタグを列挙するために必要な ItemIdの完全なリストを提供します。
2 を使用して、最初の N 個の ItemId 値 (N は表示ページ サイズ) を提供し、Item テーブルで Item 詳細情報を検索します。
完全なリストを並べ替える必要がないことに注意してください (または、別の順序で並べ替えたほうがよい場合があります)。そのため、2 番目のリストは、ユーザーの選択に基づいて並べ替える必要があります (たとえば、日付順で降順、またはタイトル順でアルファベット昇順)。 )。また、ソート順が必要な場合、クエリのコストは完全なリストを処理することを意味することに注意してください (SQL 自体による奇妙な最適化や非正規化を避けて、SQL はそのリストの最後のレコードを「見る」必要があります)。 、それらが一番上に属している場合は、ソートごとに)。
この後者の事実は、両方の目的でまったく同じクエリを使用することを支持し、対応するリストを一時テーブルに格納できます。一般的なフローは、上位 N 個の Item レコードをその詳細とともにすばやく検索し、これを一度にアプリケーションに返すことです。その後、アプリケーションは絞り込み用のタグのリストを ajax 形式で取得できます。このリストは、サブクエリが「select * from temporaryTable」に置き換えられた上記のクエリと同様のクエリで生成されます。SQL オプティマイザーがこのリストをソートすることを決定する可能性は高く (場合によっては)、2 番目に推測して明示的にソートするのではなく、そうさせましょう。
考慮すべきもう1つのポイントは、上記のようにではなく、「駆動クエリ」内のItemTagMapテーブルに結合することです。パフォーマンスのためにも、2 番目の目的 (アイテムのページの表示) に適したリストを作成するためにも、おそらくそうするのが最善です。
上記のクエリ/フローは、比較的控えめなハードウェアでも、かなりうまくスケーリングされる可能性があります。暫定的に 1/2 ミリオン以上のアイテムに、持続的なユーザー検索はおそらく 1 秒あたり最大 10 まで可能です。重要な要素の 1 つは、最初の検索基準の選択性です。
最適化のアイデア
- [典型的な検索ケースとデータ統計に応じて] Item のフィールドの一部を ItemTagMap テーブルに持ってくる (実際には複製する) ことによって、非正規化することが理にかなっている場合があります。特に短いフィールドは「歓迎」される場合があります。
- データが 100 万以上のアイテムに成長するにつれて、いくつかのタグの典型的な強い相関関係を利用することができます (例: SO では、PHP は多くの場合 MySql に付属していますが、正当な理由がないことがよくあります...)、さまざまなトリックを使用します。たとえば、「マルチタグ」TagId を導入すると、入力ロジックが少し複雑になる可能性がありますが、Map サイズを大幅に縮小することもできます。
-- '何も言わなかった! --
実際の要件と効果的なデータ統計プロファイルに照らして、適切なアーキテクチャと最適化を選択する必要があります...