1

私は2つのテーブルを持っています:urls(インデックス付きページのあるテーブル、ホストはインデックス付きの列、30 mln行)hosts(ホストに関する情報のあるテーブル、ホストはインデックス付きの列、1mln行)

私のアプリケーションで最も頻繁に使用されるSELECTの1つは、次のとおりです。

SELECT urls.* FROM urls
JOIN hosts ON urls.host = hosts.host
WHERE urls.projects_id = ?
    AND hosts.is_spam IS NULL
ORDER by urls.id DESC, LIMIT ?

URLテーブルに100000行を超えるプロジェクトでは、クエリの実行が非常に遅くなります。

テーブルが大きくなったため、クエリの実行はますます遅くなります。非常に大きなテーブルを処理するように設計されたNoSQLデータベース(MongoDBなど)についてたくさん読んだことがありますが、データベースをPgSQLからMongoDBに変更することは私にとって大きな問題です。今、私はPgSQLソリューションを最適化してみたいと思います。何かアドバイスはありますか?私は何をすべきか?

4

2 に答える 2

2

このクエリは、提供されているインデックスと組み合わせて高速にする必要があります。

CREATE INDEX hosts_host_idx ON hosts (host)
WHERE is_spam IS NULL;

CREATE INDEX urls_projects_id_idx ON urls (projects_id, id DESC);

SELECT *
FROM   urls u
WHERE  u.projects_id = ?
AND    EXISTS (
    SELECT 1
    FROM   hosts h USING (host)
    WHERE  h.is_spam IS NULL
    )
ORDER  BY urls.id DESC
LIMIT  ?;

インデックスはより重要な要素です。あなたが持っているJOIN構文は同じくらい速いかもしれません。最初のインデックスは部分インデックスであり、2番目は2番目の列に順序がある複数列のインデックスであることに注意してください。DESC

データ分散の詳細に大きく依存します。パフォーマンスとインデックスが使用されているかどうかを確認するには、(いつものように)EXPLAINANALYZEでテストする必要があります。

パフォーマンスの最適化に関する一般的なアドバイスも適用されます。あなたはドリルを知っています。

于 2012-07-09T21:05:59.047 に答える
0

hosts.host列にインデックスを追加し(主にhostsテーブルにありますが、これは重要です)、ステートメントをurls.projects_id, urls.id実行してすべての統計を更新し、スパムの割合に関係なく1秒未満のパフォーマンスを監視します。ANALYZE

ほとんどすべてが常にスパムであり、「プロジェクト」が何であれ、数が少なく、それぞれが非常に大きい場合は、わずかに異なるアドバイスが適用されます。

説明:統計の更新により、オプティマイザーはテーブルurlshostsテーブルの両方が非常に大きいことを認識できるようになります(スキーマを表示しなかったため、行サイズがわかりません)。で始まる複合インデックスは、ほとんどのコンテンツを除外しprojects.id、その2urls番目のコンポーネントは、残りのコンテンツを目的の順序ですぐにフィードするため、のインデックススキャンがによって選択されたクエリプランの基礎になるurls可能性が非常に高くなります。urlsプランナー。hosts.host次に、ホストのルックアップを効率的にするためにインデックスを付けることが不可欠です。この大きなテーブルの大部分には、まったくアクセスされません。


1)ここで、projects_idは適度に選択的であると想定します(テーブル全体で同じ値ではない)。

于 2012-07-09T21:01:09.770 に答える