-1

1 年間の毎日の時間間隔を設定する必要があるキャンペーンがあります。

例えば:

月曜日を除く年中毎日再生され、火曜日の 7 時から 9 時 30 分までは再生されません。

構造を SQL データベースに効果的に格納するにはどうすればよいですか? 365 日と 48 時間の 30 分の間隔があります。非効率的であるため、異なるテーブルへの外部キーを使用したくありません。

ありがとうございました。

4

1 に答える 1

1

最も単純なテーブルは次のようになります。30 分の時間セグメントの終わりが明示的に格納されていないため、これは最適な構造ではない可能性があります。それにもかかわらず 。. .

create table campaign_times (
  campaign_name varchar(35) not null,
  time_segment timestamp not null,
  play boolean not null default true,
  primary key (campaign_name, time_segment)
);

ランダムなキャンペーン名 (約 175 個) を大量に生成し、これらの名前を 1 年間の 30 分間隔 (3,083,520 行) でクロス結合しました。time_segment にインデックスが必要であることはわかっていました。PostgreSQL が使用できる場合に備えて、再生用のインデックスも追加しました。(PostgreSQL は、選択性の低いカラムをインテリジェントに処理することで、過去に何度も驚かされました。)

create index on campaign_times (time_segment);
create index on campaign_times (play);

統計が最新であることを確認してください。

analyze campaign_times;

では、この状況が実際にどれほど悪いか見てみましょう。

explain analyze
select *
from campaign_times 
where current_timestamp between time_segment and time_segment + interval '30 minutes'
  and play = true;

"Index Scan using campaign_times_time_segment_idx on campaign_times  
[snip]
"Total runtime: 498.713 ms"

300 万行のテーブルから現在の再生リストを取得するのに 0.5 秒未満。また、古い行を削除する、より思慮深いインデックスを試す、保存する行数を減らす(今日の日付の 1 か月前など) などの最適化について考える必要もありません。

私はそれで暮らすことができます。


本番環境では、外部キーとチェック制約が必要です。これらは PostgreSQL の SELECT ステートメントの速度には影響しません。また、MySQL の SELECT 速度にも影響しないと思います。(まあ、チェック制約は確かにそうではありません。なぜなら、MySQL はそれらを強制しないからです。)

于 2013-03-30T03:05:01.543 に答える