0

次のデータベース設定があるとします(実際に持っているものから簡略化されたバージョン):

Table: news_posting (500,000+ entries)
| --------------------------------------------------------------|
| posting_id  | name      | is_active   | released_date | token |
| 1           | posting_1 | 1           | 2013-01-10    | 123   |
| 2           | posting_2 | 1           | 2013-01-11    | 124   |
| 3           | posting_3 | 0           | 2013-01-12    | 125   |
| --------------------------------------------------------------|
PRIMARY posting_id
INDEX sorting ON (is_active, released_date, token)

Table: news_category (500 entries)
| ------------------------------|
| category_id   | name          |
| 1             | category_1    |
| 2             | category_2    |
| 3             | category_3    |
| ------------------------------|
PRIMARY category_id

Table: news_cat_match (1,000,000+ entries)
| ------------------------------|
| category_id   | posting_id    |
| 1             | 1             |
| 2             | 1             |
| 3             | 1             |
| 2             | 2             |
| 3             | 2             |
| 1             | 3             |
| 2             | 3             |
| ------------------------------|
UNIQUE idx (category_id, posting_id)

私のタスクは次のとおりです。アクティブで、今日の日付より前で、リクエストで指定された 20 ほどのカテゴリの 1 つにある 50 件の最新のニュース投稿 (あるオフセットで) のリストを取得する必要があります。返す 50 件のニュース投稿を選択する前に、適切なニュース投稿をトークンで降順に並べ替える必要があります。私のクエリは現在、次のようになっています。

SELECT DISTINCT posting_id
FROM news_posting np
INNER JOIN news_cat_match ncm ON (ncm.posting_id = np.posting_id AND ncm.category_id IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20))
WHERE np.is_active = 1
AND np.released_date < '2013-01-28'
ORDER BY np.token DESC LIMIT 50

1 つだけを指定category_idすると、重複した結果の削除を処理する必要がないため、クエリは a を含まず、filesortかなり高速です。EXPLAINただし、複数の を含む上記のクエリを呼び出すと、実行する必要category_idがあることを示すテーブルが返さfilesortれます。また、私のデータセットではクエリが非常に遅くなります。

テーブルのセットアップやクエリを最適化する方法はありますか?

4

1 に答える 1

0

上記のクエリを次のように書き直すことで、単一値のカテゴリ リスト バージョンよりもさらに高速に実行することができました。

SELECT posting_id
FROM news_posting np
WHERE np.is_active = 1
AND np.released_date < '2013-01-28'
AND EXISTS (
    SELECT ncm.posting_id
    FROM news_cat_match ncm 
    WHERE ncm.posting_id = np.posting_id
    AND ncm.category_id IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
    LIMIT 1
)
ORDER BY np.token DESC LIMIT 50

私のデータセットでは、これに 1 秒もかかりません。

category_id悲しいことに、これは 1 つしか指定されていない場合よりもさらに高速です。これは、ニュース項目のサブセットが 1 つだけの場合よりも大きいcategory_idため、結果がより迅速に見つかるためです。

さて、私の次の質問は、カテゴリに時間内に広まるニュースがほとんどない場合に、これを最適化できるかどうかです。

以下は、私の開発マシンではまだかなり遅いです。本番サーバーでも十分高速ですが、可能であればこれを最適化したいと考えています。

SELECT DISTINCT posting_id
FROM news_posting np
INNER JOIN news_cat_match ncm ON (ncm.posting_id = np.posting_id AND ncm.category_id = 1)
WHERE np.is_active = 1
AND np.released_date < '2013-01-28'
ORDER BY np.token DESC LIMIT 50

他に何か提案はありますか?

于 2013-01-29T19:48:59.570 に答える