web-dev-qa-db-ja.com

テーブルから最後の行をフェッチする最も速い方法は何ですか?

列を持つPostgreSQLテーブルPricesがあります。

  • price(10進数)
  • product_id(整数)

もあります created_atおよびupdated_at列。

価格は定期的に更新され、古い価格はテーブルに保持しています。特定の製品について、表の最後の価格は現在の価格です。

特定の製品の最終価格を取得する最も効率的な方法は何ですか。

  • インデックスproduct_idと最後のレコードのクエリ
  • 3番目の列active(ブール)を追加して最新の価格をマークし、複合インデックス(product_idおよびactive
  • または、他の何か?
11
Mike81

ソリューションに関係なく、product_idのインデックスが必要になります。

Updated_at列にインデックスがあり、必要なのは、指定した「特定の製品」をフェッチすることだけである場合は、次のようにします。

select *
from Prices
where product_id = ?
order by updated_at desc 
limit 1

しかし、希望する結果が得られなかった場合、または多くの製品の現在の価格を取得する必要がある場合は、アクティブな列を追加し、新しい列以外のすべての価格でNに設定するオプションを試してみます。価格の更新後、a_horse_with_no_nameで提案されているように、アクティブな部分インデックスを作成します。以前の価格行をアクティブにしないように更新するという複雑なレイヤーを追加するので、必要な場合にのみそこに行きます。

11
ETL

データベースの残りの部分の知識がなければ、製品の価格のフェッチを高速化するために少しの非標準形式を用意することができます(各アイテムに1つの価格があると仮定します)。

priceテーブルにlast_priceof type productという名前の新しい列を作成し、priceテーブルにトリガーAFTER INSERT ON EACH ROWを作成するだけです。新しい価格が作成されるたびに、関連製品が最新の価格で更新されます。この方法では、製品をフェッチするたびに、その最終価格もフェッチします。

バージョン9.3以降、PostgreSQLはマテリアライズドビューをサポートしています。これは、データを非正規化し、書き込み用の通常の形式と読み取り用の非正規化ビューを維持するための良い方法です。ビューの更新は、PostgresのLISTEN/NOTIFYメカニズムによってトリガーできます。

5
greg