sql >> Databasteknik >  >> RDS >> PostgreSQL

Optimera/indexera tidszonsfråga

Om du faktiskt har en kolumn av typen timestamp och tolka den (i delar) beroende på den aktuella tidszonen, och denna tidszon kan variera, då är ett index i allmänhet omöjligt . Du kan bara bygga ett index på IMMUTABLE data ...

Efter uppdatering:

För att svara på dessa frågor:

  1. Vilka bokningar börjar "idag"?
  2. Vilka bokningar har startdatum i framtiden?
  3. Vilka bokningar har tidigare startdatum?

... det är bäst att lagra en timestamp with time zone . Bara ett date är inte tillräckligt exakt.

Så länge vi bara är intresserade av det lokala "idag" (enligt definitionen av aktuell tidszon ), gör vi inte måste spara tidszonen explicit. Vi bryr oss inte om var i världen det händer, vi behöver bara en absolut tid att jämföra med.

Sedan, för att få bokningar från och med "idag" helt enkelt:

SELECT *
FROM   reservations
WHERE  start_on::date = current_date;

Men det här är inte sargbart eftersom start_on::date är ett härlett uttryck och vi kan inte heller bygga ett funktionellt index för detta (utan smutsiga trick) eftersom uttrycket beror på den aktuella tidszonen och inte är IMMUTABLE .

Istället , jämför med början och slutet av "vår" dag i UTC-tid:

SELECT *
FROM   reservations
WHERE  start_on >= current_date::timestamptz
AND    start_on < (current_date + 1)::timestamptz; -- exclude upper border

Nu kan detta enkla index stödja frågan:

CREATE INDEX ON reservations (start_on);

Demo

SQL Fiddle är nere i ATM. Här är en liten demo för att förstå:

CREATE TEMP TABLE reservations (
   reservation_id serial
 , start_on timestamptz NOT NULL
 , time_zone text);    -- we don't need this

INSERT INTO reservations (start_on, time_zone) VALUES
  ('2014-04-09 01:00+02', 'Europe/Vienna')
, ('2014-04-09 23:00+02', 'Europe/Vienna')
, ('2014-04-09 01:00+00', 'UTC')    -- the value is independent of the time zone
, ('2014-04-09 23:00+00', 'UTC')    -- only display depends on current time zone
, ('2014-04-09 01:00-07', 'America/Los_Angeles')
, ('2014-04-09 23:00-07', 'America/Los_Angeles');

SELECT start_on, time_zone 
     , start_on::timestamp             AS local_ts
     , start_on AT TIME ZONE time_zone AS ts_at_tz
     , current_date::timestamptz       AS lower_bound
     , (current_date + 1)::timestamptz AS upper_bound
FROM   reservations
WHERE  start_on >= current_date::timestamptz
AND    start_on < (current_date + 1)::timestamptz;

Mer förklaring och länkar här:
Ignorerar tidszoner helt och hållet i Rails och PostgreSQL



  1. Vad är syftet med en IMPLICIT JOIN i sql?

  2. Hur berättar man för node.js att mysql inte körs på standardporten?

  3. Frågegrupp efter par av kolumnresultat

  4. Få postgresql-arrayen till struct med StructScan