sql >> Database >  >> RDS >> PostgreSQL

Tijdzone-query optimaliseren/indexeren

Als u daadwerkelijk een kolom van het type timestamp . heeft en interpreteer het (in delen) afhankelijk van de huidige tijdzone, en deze tijdzone kan variëren, dan is een index over het algemeen onmogelijk . U kunt alleen een index bouwen op IMMUTABLE gegevens ...

Na update:

Om deze vragen te beantwoorden:

  1. Welke reserveringen beginnen "vandaag"?
  2. Welke reserveringen hebben startdata in de toekomst?
  3. Welke reserveringen hebben een startdatum in het verleden?

... je het beste een timestamp with time zone . Gewoon een date is niet precies genoeg.

Zolang we alleen geïnteresseerd zijn in het lokale "vandaag" (zoals gedefinieerd door de huidige tijdzone ), doen we niet moet de tijdzone expliciet opslaan. Het maakt ons niet uit waar ter wereld het gebeurt, we hebben alleen een absolute tijd nodig om mee te vergelijken.

Om vervolgens "vandaag" reserveringen te krijgen:

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

Maar dit is niet sargable omdat start_on::date is een afgeleide uitdrukking en we kunnen hier ook geen functionele index voor bouwen (zonder vuile trucs) omdat de uitdrukking afhangt van de huidige tijdzone en niet IMMUTABLE is .

In plaats daarvan , vergelijk met het begin en einde van "onze" dag in UTC-tijd:

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

Nu kan deze eenvoudige index de zoekopdracht ondersteunen:

CREATE INDEX ON reservations (start_on);

Demo

SQL Fiddle heeft geen ATM. Hier is een kleine demo om het te begrijpen:

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;

Meer uitleg en links hier:
Tijdzones volledig negeren in Rails en PostgreSQL



  1. Meerdere rijen toevoegen met Invoegen ... OP DUPLICATE KEY UPDATE met knex

  2. PostgreSQL - Quartz JDBC-JobStoreTX - getTriggersForJob - ArrayIndexOutOfBoundsException

  3. Combineer INSERT en SELECT in één SQL-query (Zapier)

  4. hoe het databaseschema correct te specificeren in springboot?