1

アプリ用のデータベースを構築しており、より大きなデータ セットでパフォーマンスの問題をテストしています。約 250,000 の位置レコードを生成しました。各場所は多くのカテゴリに割り当てることができ、カテゴリは多くの場所に割り当てることができます。私のデータセットには、各場所に割り当てられた 2 ~ 4 のカテゴリがあります。

ワイルドカード検索を使用して許可するカテゴリをフィルタリングすることで、ユーザーが場所を検索できるようにしたいと考えています。したがって、「赤」という単語が含まれるすべてのカテゴリを一致させたいと思うかもしれません。したがって、「赤」と入力すると、カテゴリ タイトルに「赤」が含まれるすべての場所が表示されます。さらに、同じ文字列で場所のタイトルをワイルドカード検索したいと考えています。

機能するクエリを作成しましたが、大規模なデータセットではパフォーマンスが低下します。基本的に、制限が設定されていて、結果がすぐに見つかる場合 (約 .05ms) に問題ない内部クエリを使用しています。すぐに結果が見つからない場合は、データベース全体を調べて、クエリに約 9 ~ 10 秒かかるようです。

これが私のデータベースの簡略化されたレイアウトです:

locations: id | title | address
categories: id | title
locations_categories: id | location_id | category_id

現在使用しているクエリは次のとおりです。

SELECT `id`,`title`,`address`
FROM (`locations`)
WHERE title LIKE '%string%'
AND WHERE id IN (
 SELECT location_id 
 FROM locations_categories 
 JOIN categories ON categories.id = locations_categories.category_id 
 WHERE categories.title LIKE '%string%')
4

2 に答える 2

1

あなたの説明計画はこれを確認(または反証)しますが、あなたの問題は句の先頭の % であると思われます

WHERE categories.title LIKE '%string%' 

WHERE title LIKE '%string%`

テーブル全体のスキャンを強制します。これに対処するには、問題のドメインとアプリケーションに関する知識が必要になることがよくあります。

簡単な方法は、「で始まる」のみを検索することです。その他には、全文検索、関数ベースのインデックス、既知の検索に関連するレコードを事前に並べ替えて一覧表示する「グループ化テーブル」があります。

于 2013-05-04T22:01:08.333 に答える
1

まず、メイン クエリはサブクエリの値を使用するだけなので、書き換えることができます。

 SELECT location_id 
 FROM locations_categories 
 JOIN categories ON categories.id = locations_categories.category_id 
 WHERE categories.title LIKE '%string%'

しかし、このクエリを 2 つに分割することを提案します。大きなデータセットでは、JOIN は低速で​​す。最初に、必要なカテゴリ ID を取得します (ページングを使用):

SELECT id
FROM categories
WHERE title LIKE '%string%' LIMIT BY <start>, <step>

次に、locations_categories を取得できます。

SELECT location_id FROM locations_categories WHERE category_id IN (...)

そして、取得したロケーション ID を使用して、対応するレコードを取得します。

SELECT * FROM locations WHERE id IN (...)

これら 3 つのクエリを組み合わせると、元のクエリよりもはるかに高速になります。

また、タイトル列がインデックス化されていることを確認してください。これがボトルネックになる可能性があります。ただし、検索語の先頭にワイルドカードがあるため、FULLTEXTここではインデックスを使用する必要があります。

于 2013-05-04T19:21:07.543 に答える