1

私は現在、目的が終了したときに統計を更新する必要があるスクリプトをPHPで作成しています。スクリプトはWebブラウザからアクセスされ、トラフィックによっては同時に実行される場合があります。私は統計が正しいことを保証しなければなりません。

あなたに写真を与えるために、私たちがテーブルを持っているとしましょう:

CREATE TABLE statistics(
  user_id      integer NOT NULL,
  date         integer NOT NULL, -- for unix time
  stat1        integer NOT NULL DEFAULT 0,
  stat2        integer NOT NULL DEFAULT 0,
  stat3        integer NOT NULL DEFAULT 0  -- and so on...
);

-- Let's insert some testing data for a couple of users and days...
-- Day one
INSERT INTO statistics(1, 1303520820, 1, 1, 1);
INSERT INTO statistics(2, 1303520820, 1, 1, 1);
-- Day two
INSERT INTO statistics(1, 1303603200, 1, 1, 1);
INSERT INTO statistics(2, 1303603200, 1, 1, 1);
-- Day three
INSERT INTO statistics(1, 1303689600, 1, 1, 1);
INSERT INTO statistics(2, 1303689600, 1, 1, 1);

毎日新しい行がテーブルに挿入されるため、日次、週次、月次、年次の統計を取得できます。user_idごとに1日に1行だけ挿入されるようにする必要があります。また、UPDATEクエリが実行されるたびに、列stat1stat2stat3が適切にインクリメントされます。

このスクリプトにはかなりのトラフィックが予想されるため、スクリプトが実行され、いくつかのインスタンスが同時に動作しているときに、どのように動作させるかを理解したいと思います。そのようなタスクに最適な方法/手法は何ですか?

4

3 に答える 3

3

最も簡単な解決策は、一意の制約を追加することです

CREATE TABLE statistics(
  user_id      integer NOT NULL,
  date         integer NOT NULL, -- for unix time
  stat1        integer NOT NULL DEFAULT 0,
  stat2        integer NOT NULL DEFAULT 0,
  stat3        integer NOT NULL DEFAULT 0,  -- and so on...
  UNIQUE(user_id,date)
);

他にどのような対策を講じているかに関係なく、必ずこれを行う必要があります。

于 2011-04-22T22:51:01.420 に答える
1

他の人が言っているように、user_idとdateのペアに一意の制約が必要です。

複合キー(user_id、date)が存在しない場合に算術演算を行わずに挿入し、複合キー存在する場合に算術演算で更新するには、コードを記述する必要があります。非公式には、これは「アップサート」と呼ばれます。複数の方法があります。

PosgreSQLドキュメントには、例外処理を使用してこの種の要件を実装する関数の例があります。関数の問題は、アプリケーションコードやデータベースの女の子に例外なく毎回それを使用させることができないことです。

あなたは(私が思うに)suppress_redundant_updates_trigger()を使うことができます。トリガーの利点は、アプリケーションコードやデータベースガールによって誤ってバイパスされないことです。私自身はこのテクニックを使ったことがないので、これ以上コメントすることはできません。このトリガーはここに記載されています。

ユーザー定義のトリガーを使用してアップサートロジックを処理することもできます。

于 2011-04-23T05:30:46.890 に答える
1

また、日付値のCHECKを追加して、1日の倍数になるようにすることもできます。

ALTER TABLE "statistics" ADD CONSTRAINT "1day_quantum" CHECK ("date" = ("date" / 86400)::INTEGER * 86400);

次に、日付の間違った値を挿入しようとすると、例外がスローされます。

日付フィールドタイプがTIMESTAMPまたはTIMESTAMPTZの場合、CHECKはより複雑になります。

ALTER TABLE "statistics" ADD CONSTRAINT "1day_quantum" CHECK ("date" = TIMESTAMP 'epoch' + ((EXTRACT(EPOCH FROM "date") / 86400)::INTEGER * 86400) * INTERVAL '1 second');

86400(秒数)を変更することにより、制約をさまざまな量に調整できます。たとえば、15分間で900です。

于 2015-10-15T10:13:55.670 に答える