web-dev-qa-db-ja.com

PostgreSQLのカウンターの同時増分

アイテムとその使用法のリストで構成されるプロジェクトの統計表を維持する必要があります(ページビューをカウントするWebサイトのようなものを考えてください)。アイテムがインスタンス化されるたびに、特定のアイテムの使用量を増やす必要があります。

私の最初の実装は:

statistics(
  id      integer NOT NULL,
  name    character varying(255) NOT NULL,
  usage   integer NOT NULL DEFAULT 0,
);


UPDATE statistics 
  SET usage = usage + 1
WHERE name = '<name>';

私の懸念は、パフォーマンスと並行性についてです。更新プロセスは数十(おそらく80〜120)デバイスによってインスタンス化され、1秒あたり数回発生する可能性があるため、私の質問は次のとおりです。

1)このメソッドは並行性を維持しますか? (つまり、複数のデバイスが「同時に」更新を要求した場合、すべて要求はカウントされますか?)

2)結果を達成するための最良の方法を提案できますか?更新の書き込みには負荷がかかると思いますが、読み取りの方がはるかに頻繁です。値を増やす特定の機能はありますか?私は「シーケンス」を見ていますが、それが正しい方法であるかどうかはわかりません...

アドバイスをよろしくお願いします

9
eng.student

2番目の更新は、同じ行の前の更新がコミットされるのを待ちますが、コミットされた値を参照します。

2つの同時トランザクションが同じ行を初期値0で更新すると仮定します。

時間トランザクション1 T1値トランザクション2 T2値
 ------------------------------- ------------------------------- 
 1 update ... 1 0 
 2 1更新..「未定義」
(待機)
 3コミット1 2 
 4 1コミット2 
 5 2 2 

「T1値」および「T2値」は、そのトランザクションが認識する値を意味します。

「互換性のない」変更(たとえば、1つのトランザクションがusage列をインクリメントするのではなく特定の値に設定するトランザクション)がある状況を確実にキャッチしたい場合は、すべてのトランザクションを「シリアライズ可能」に配置できます。分離レベル。ただし、その場合はエラー処理の準備をする必要があります。

異なる名前への更新は、待機せずに同時に実行できます(異なる行が影響を受けるため)。

SELECTsがブロックされることはなく、コミットされた値のみが表示されます。