2

最新の 50 件のニュース記事を取得するための非常に単純な PostgreSQL クエリがあります。

SELECT id, headline, author_name, body 
 FROM news 
 ORDER BY publish_date DESC 
 LIMIT 50

ここで、各記事の最新の 10 件のコメントも取得したいと考えています。それらを取得するには 2 つの方法が考えられますが、PostgreSQL のコンテキストでどちらが最適かはわかりません。


オプション1:

元のクエリのコメントに対して直接サブクエリを実行し、結果を配列にキャストします。

SELECT headline, author_name, body,
  ARRAY(
   SELECT id, message, author_name,
     FROM news_comments
     WHERE news_id = n.id
     ORDER BY DATE DESC
     LIMIT 10
  ) AS comments
 FROM news n
 ORDER BY publish_date DESC 
 LIMIT 50

明らかに、この場合、アプリケーション ロジックは、配列内のどのインデックスがどの列であるかを認識している必要がありますが、それは問題ありません。

このメソッドで私が目にする 1 つの問題は、クエリ プランナーがそれをどのように実行するかがわからないことです。これは事実上 51 個のクエリに変わるでしょうか?


オプション 2:

元の非常に単純なクエリを使用します。

SELECT id, headline, author_name, body 
 FROM news 
 ORDER BY publish_date DESC 
 LIMIT 50

次に、アプリケーション ロジックを介して、すべてのニュース ID を収集し、それらを別のクエリで使用します。ニュース記事ごとの結果の数を制限するには、ここで row_number() を使用する必要があります。

SELECT *
FROM (
    SELECT *,
        row_number() OVER(
            PARTITION BY author_id
            ORDER BY author_id DESC
        ) AS rn
    FROM (
        SELECT *
          FROM news_comment
          WHERE news_id IN(123, 456, 789)
    ) s
) s
where rn <= 10

このアプローチは明らかにより複雑であり、最初に範囲指定されたニュース記事のすべてのコメントを取得してから、行数が 10 を超えるコメントを切り捨てる必要があるかどうかはわかりません。


どのオプションが最適ですか? または、私が見落としたさらに良い解決策はありますか?

文脈上、これは私が自分で開発したニュース アグリゲーター サイトです。現在、いくつかのカテゴリにわたって約 40,000 のニュース記事があり、約 500,000 のコメントがあります。

4

1 に答える 1

3

少なくとも を使用して、ステートメントの実行計画を調査する必要がありますEXPLAIN ANALYZE。これにより、ステートメント自体の実行中にオプティマイザーによって選択された計画が提供され、実際の実行時間やその他の統計も返されます。

もう 1 つの解決策は、LATERALサブクエリを使用してニュースごとに 10 個のコメントを別々の行で取得することですが、これもまた、計画を調査して比較し、最適なアプローチを選択する必要があります。

SELECT 
  n.id, n.headline, n.uathor_name, n.body, 
  c.id, c.message, c.author_name
FROM news n
LEFT JOIN LATERAL ( 
  SELECT id, message, author_name
  FROM news_comments nc
  WHERE n.id = nc.news_id
  ORDER BY nc.date DESC
  LIMIT 10
  ) c ON TRUE
ORDER BY publish_date DESC
LIMIT 50

クエリにニュースLATERALから取得した各行の相互参照が含まれている場合、 LATERAL は connection in句を使用して評価されます。したがって、それを繰り返し実行し、ソース テーブルnewsの各行に対して取得した情報を結合します。WHERE

このアプローチは、アプリケーション ロジックがオプション 1から出てくる配列を処理するのに必要な時間を節約し、オプション 2のようにニュースごとに多くの個別のクエリを発行する必要がないため、(この場合) 個別のトランザクションを開き、確立するのに必要な時間を節約できます。接続、行の取得など...

インデックスを作成し、プランナーが行った選択を理解するために実験できるプランナーのコスト定数とプランナー メソッドの構成パラメーターを調べて、パフォーマンスの改善を探すのは良いことです。詳細については、こちらをご覧ください。

于 2016-09-18T18:29:00.313 に答える