Как создать секционированную последовательность PostgreSQL? - PullRequest
5 голосов
/ 28 августа 2010

Существует ли простой (т.е. не хакерский) и свободный от гонки способ создания секционированной последовательности в PostgreSQL. Пример:

Использование нормальной последовательности в выпуске:

| Project_ID | Issue |
| 1          | 1     |
| 1          | 2     |
| 2          | 3     |
| 2          | 4     |

Использование секционированной последовательности в выпуске:

| Project_ID | Issue |
| 1          | 1     |
| 1          | 2     |
| 2          | 1     |
| 2          | 2     |

1 Ответ

2 голосов
/ 07 сентября 2010

Я не верю, что есть простой способ, который так же прост, как регулярные последовательности, потому что:

  1. В последовательности хранится только один поток чисел (следующее значение и т. Д.). Вы хотите один для каждого раздела.
  2. Последовательности имеют специальную обработку, которая обходит текущую транзакцию (чтобы избежать условия гонки). Трудно воспроизвести это на уровне SQL или PL / pgSQL без использования таких трюков, как dblink.
  3. Свойство столбца DEFAULT может использовать простое выражение или вызов функции, например nextval('myseq'); но он не может ссылаться на другие столбцы, чтобы сообщить функции, из какого потока должно поступить значение.

Вы можете сделать что-то, что работает, но вы, вероятно, не будете думать, что это просто. Решение указанных проблем по очереди:

  1. Используйте таблицу для хранения следующего значения для всех разделов со схемой, подобной multiseq (partition_id, next_val).
  2. Напишите функцию multinextval(seq_table, partition_id), которая выполняет что-то вроде следующего:

    1. Создание новой транзакции, независимой от текущей транзакции (один из способов сделать это - через dblink; я полагаю, что некоторые другие языки сервера могут сделать это проще).
    2. Блокировка таблицы, упомянутой в seq_table.
    3. Обновите строку, в которой идентификатор раздела равен partition_id, с увеличенным значением. (Или вставьте новую строку со значением 2, если ее еще нет.)
    4. Передать эту транзакцию и вернуть предыдущий сохраненный идентификатор (или 1).
  3. Создайте триггер вставки в таблице проектов, в котором для вставки используется вызов multinextval('projects_table', NEW.Project_ID).

Я не использовал весь этот план сам, но я пробовал что-то похожее на каждый шаг в отдельности. Примеры функции multinextval и триггера могут быть предоставлены, если вы хотите попробовать это ...

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