PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Добавяне на ограничение за дата и час към частичен индекс с няколко колони на PostgreSQL

Получавате изключение, като използвате now() защото функцията не е IMMUTABLE (очевидно) и, цитирайки ръководството :

Виждам два начина за използване на (много по-ефективен) частичен индекс:

1. Частичен индекс с условие, използващо константа дата:

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

Приемаме created всъщност се дефинира като timestamp . Няма да работи, ако предоставите timestamp константа за timestamptz колона (timestamp with time zone ). Актьорският състав от timestamp към timestamptz (или обратно) зависи от текущата настройка на часовата зона и не е неизменна . Използвайте константа от съответстващ тип данни. Разберете основите на времевите клейма с/без часова зона:

Пуснете и създайте отново този индекс в часове с нисък трафик, може би с cron работа на дневна или седмична база (или каквото е достатъчно добро за вас). Създаването на индекс е доста бързо, особено на частичен индекс, който е сравнително малък. Това решение също не трябва да добавя нищо към таблицата.

Ако приемем, че няма едновременен достъп към таблицата, автоматичното повторно създаване на индекс може да се извърши с функция като тази:

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$;

Обаждане:

SELECT f_index_recreate();

now() (както имахте) е еквивалент на CURRENT_TIMESTAMP и връща timestamptz . Прехвърляне към timestamp с now()::timestamp или използвайте LOCALTIMESTAMP вместо това.

db<>fiddle тук
Стар sqlfiddle

Ако трябва да се справите с едновременен достъп към таблицата, използвайте DROP INDEX CONCURRENTLY и CREATE INDEX CONCURRENTLY . Но не можете да обвиете тези команди във функция, защото по документация :

И така, с две отделни транзакции :

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

След това:

DROP INDEX CONCURRENTLY IF EXISTS queries_recent_idx;

По желание преименувайте на старо име:

ALTER INDEX queries_recent_idx2 RENAME TO queries_recent_idx;

2. Частичен индекс с условие за "архивиран" таг

Добавете archived маркирайте към вашата таблица:

ALTER queries_query ADD COLUMN archived boolean NOT NULL DEFAULT FALSE;

UPDATE колоната на избрани от вас интервали за „пенсиониране“ на по-стари редове и създаване на индекс като:

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

Добавете условие за съвпадение към вашите заявки (дори ако изглежда излишно), за да му позволите да използва индекса. Проверете с EXPLAIN ANALYZE дали плановщикът на заявки се хваща - трябва да може да използва индекса за заявки на по-нова дата. Но няма да разбере по-сложни условия, които не съвпадат точно.

Не е нужно да премахвате и създавате отново индекса, а UPDATE на масата може да е по-скъпо от пресъздаването на индекса и масата става малко по-голяма.

Бих отишла с първия опция (индекс отдих). Всъщност използвам това решение в няколко бази данни. Вторият изисква по-скъпи актуализации.

И двете решения запазват полезността си с течение на времето, производителността бавно се влошава, тъй като в индекса се включват повече остарели редове.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. как да проверите вида на стойността в postgres

  2. Изброяване на дяловете на таблицата в таблицата на Postgres

  3. Привилегии и сигурност на PostgreSQL - Заключване на публичната схема

  4. Осмисляне на размерите на редовете в Postgres

  5. Не може да мигрира на Heroku