PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Dodaj ograniczenie daty i czasu do wielokolumnowego indeksu częściowego PostgreSQL

Otrzymasz wyjątek za pomocą now() ponieważ funkcja nie jest IMMUTABLE (oczywiście) i cytując podręcznik :

Widzę dwa sposoby wykorzystania (znacznie wydajniejszego) indeksu częściowego:

1. Indeks częściowy z warunkiem przy użyciu stałej data:

CREATE INDEX queries_recent_idx ON queries_query (user_sid, created)
WHERE created > '2013-01-07 00:00'::timestamp;

Zakładając created jest faktycznie zdefiniowany jako timestamp . Nie działałoby dostarczenie timestamp stała dla timestamp kolumna (timestamp with time zone ). Obsada z timestamp do timestamp (lub odwrotnie) zależy od aktualnego ustawienia strefy czasowej i nie jest niezmienne . Użyj stałej pasującego typu danych. Zapoznaj się z podstawami znaczników czasu ze strefą czasową / bez:

Upuść i utwórz ponownie ten indeks w godzinach o małym natężeniu ruchu, może z pracą crona na co dzień lub co tydzień (lub cokolwiek, co jest dla ciebie wystarczające). Tworzenie indeksu jest dość szybkie, zwłaszcza częściowy indeks, który jest stosunkowo mały. To rozwiązanie również nie musi niczego dodawać do tabeli.

Zakładając brak równoczesnego dostępu do tabeli, automatyczne odtwarzanie indeksu można wykonać za pomocą funkcji takiej jak ta:

CREATE OR REPLACE FUNCTION f_index_recreate()
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   DROP INDEX IF EXISTS queries_recent_idx;
   EXECUTE format('
      CREATE INDEX queries_recent_idx
      ON queries_query (user_sid, created)
      WHERE created > %L::timestamp'
    , LOCALTIMESTAMP - interval '30 days');  -- timestamp constant
--  , now() - interval '30 days');           -- alternative for timestamptz
END
$func$;

Zadzwoń:

SELECT f_index_recreate();

now() (tak jak ty) jest odpowiednikiem CURRENT_TIMESTAMP i zwraca timestamptz . Przesyłaj do timestamp z now()::timestamp lub użyj LOCALTIMESTAMP zamiast tego.

db<>fiddle tutaj
Stary sqlfiddle

Jeśli masz do czynienia z dostępem równoczesnym do tabeli użyj DROP INDEX CONCURRENTLY i CREATE INDEX CONCURRENTLY . Ale nie możesz zawinąć tych poleceń w funkcję, ponieważ według dokumentacji :

Tak więc z dwiema oddzielnymi transakcjami :

CREATE INDEX CONCURRENTLY queries_recent_idx2 ON queries_query (user_sid, created)
WHERE  created > '2013-01-07 00:00'::timestamp;  -- your new condition

Następnie:

DROP INDEX CONCURRENTLY IF EXISTS queries_recent_idx;

Opcjonalnie zmień nazwę na starą:

ALTER INDEX queries_recent_idx2 RENAME TO queries_recent_idx;

2. Częściowy indeks z warunkiem na tagu „zarchiwizowany”

Dodaj archived tag do tabeli:

ALTER queries_query ADD COLUMN archived boolean NOT NULL DEFAULT FALSE;

UPDATE kolumnę w wybranych przez Ciebie odstępach, aby „wycofać” starsze wiersze i utworzyć indeks, taki jak:

CREATE INDEX some_index_name ON queries_query (user_sid, created)
WHERE NOT archived;

Dodaj pasujący warunek do zapytań (nawet jeśli wydaje się to zbędne), aby umożliwić mu użycie indeksu. Sprawdź za pomocą EXPLAIN ANALYZE czy planer zapytań się łapie - powinien umieć używać indeksu dla zapytań w nowszym terminie. Ale nie zrozumie bardziej złożonych warunków, które nie pasują dokładnie.

Nie musisz upuszczać i ponownie tworzyć indeksu, ale UPDATE na stole może być droższe niż odtwarzanie indeksu, a stół staje się nieco większy.

Poszedłbym z pierwszym opcja (rekreacja indeksu). W rzeczywistości używam tego rozwiązania w kilku bazach danych. Drugi wiąże się z bardziej kosztownymi aktualizacjami.

Oba rozwiązania zachowują swoją użyteczność w czasie, wydajność powoli się pogarsza, ponieważ w indeksie znajdują się bardziej przestarzałe wiersze.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 3 sposoby sprawdzenia typu danych kolumny w PostgreSQL

  2. psycopg2 w rzeczywistości nie wstawia danych

  3. Znajdź przerwy w sekwencji w SQL bez tworzenia dodatkowych tabel

  4. Wiele indeksów a pojedynczy indeks w wielu kolumnach w postgresql

  5. Jak uporządkować różne krotki w zapytaniu PostgreSQL