Выбор записей из PostgreSQL после того, как первичный ключ зациклен? - PullRequest
0 голосов
/ 10 января 2019

У меня есть таблица PostgreSQL 9.5, которая настроена на цикл, когда идентификатор первичного ключа достигает максимального значения. Ради аргумента, пусть максимальное значение идентификатора может быть 999,999. Я добавлю запятые, чтобы было легче читать цифры.

Мы выполняем задание, которое удаляет данные из таблицы старше 45 дней. Предположим, что таблица теперь содержит только записи с идентификаторами 999 998 и 999 999.

Идентификатор первичного ключа возвращается к 1 и записано еще 20 записей. Мне нужно сделать его общим, чтобы я не делал никаких предположений о том, сколько было написано. В моих реальных потребностях, мне все равно, сколько было написано.

Как выбрать записи без получения дубликатов с идентификаторами 999 998 и 999 999?

Например:

SELECT * FROM my_table WHERE ID >0;

Would return (in no particular order):

999,998
999,999
1
2
...
20

В моем случае я должен публиковать все записи, которые были записаны в таблицу, посреднику сообщений. Я веду отдельную таблицу, которая отслеживает идентификатор строки и метку времени последней опубликованной записи. Псевдопросмотр / псевдоалгоритм для определения того, какие новые записи нужно написать, выглядит примерно так. Оператор IF обрабатывает, когда идентификатор первичного ключа возвращается к 1, так как мне нужно прочитать новую запись, записанную после циклического идентификатора:

SELECT * from my_table WHERE id > last_written_id
PUBLISH each record
if ID of last record published == MAX_TABLE_ID (e.g 999,999):
    ??? What to do here? I need to get the newest records where ID >= 1 but less than the oldest record I have

Я понимаю, что «код» груб, но на данный момент это просто идея, поэтому кода нет.

Спасибо

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Это совершенно другой подход: вы можете полностью заполнить таблицу, указав в ней столбец для времени удаления. Таким образом, вместо удаления строк, вы просто устанавливаете эту дату и время. И вместо того, чтобы вставить строку, вы просто обновляете ту, которая была удалена давным-давно:

update my_table
set col1 = 123, col2 = 456, col3 = 'abc', deletion_datetime = null
where deletion_datetime = 
(
  select deletion_datetime
  from my_table
  where deletion_datetime is not null
  order by deletion_datetime
  limit 1
);
0 голосов
/ 10 января 2019

Если вы можете предположить, что коэффициент заполнения диапазона меньше 0,5, это должно работать хорошо:

select *
from my_table
where 
    id > @last_written_id 
    or @last_written_id > 999999/ 2 and id < @last_written_id / 2
0 голосов
/ 10 января 2019

Хм, вы можете использовать текущее значение последовательности, чтобы сделать то, что вы хотите:

select t.*
from my_table t
where t.id > @last_written_id or
      (currval(pg_get_serial_sequence('my_table', 'id')) < @last_written_id and
       t.id <= currval(pg_get_serial_sequence('my_table', 'id')) 
      );

Это не 100% решение. В конце концов, 2 000 000 записей могли быть добавлены, поэтому все номера будут повторяться или записи будут удалены. Кроме того, если у вас есть вставки во время выполнения запроса - особенно в многопоточной среде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...