Определяемая пользователем функция соединения в Postgres? - PullRequest
2 голосов
/ 04 февраля 2020

У меня есть две таблицы T1 и T2, которые напоминают вертикальные разделы более широкой таблицы T в базе данных PostgreSQL.

Я хотел бы недорого присоединиться к этим разделам, используя операции сканирования таблиц в каждой из таблиц , аналогично операции MERGE-JOIN, которая объединяет строки попарно в новую строку. Мой подход предполагает, что таблицы могут объединяться в порядке их сканирования, без сортировки или проверки каких-либо предикатов соединения. Основная цель состоит в том, чтобы избежать явных объединений с использованием некоторого идентификатора строки, который также необходимо реплицировать во все разделы, что, по-видимому, является общим шаблоном вертикального разделения в PG.

Таблицы T1 и T2 не имеют индексов и только для чтения. Таким образом, оптимизатор не найдет альтернативного способа доступа к ним в другом порядке. Параллельный запрос отключен, чтобы избежать операций параллельного сканирования.

[устарел Q1) Учитывая эти предосторожности, есть ли какая-либо гарантия в PG, что строки всегда возвращаются в порядке вставки, например, после VACUUMing? ]

Q2) Можно ли написать UDF, который реализует MERGE-JOIN-подобные операции, то есть что-то похожее на:

SELECT T1.*, func('T2') FROM T1;

или

SELECT * FROM func('T1', 'T2');

Кажется, все сводится к написанию пользовательского оператора соединения для PG.

Еще несколько мыслей: я понимаю, что функции PL / pg SQL накапливают результат в RETURN NEXT и RETURN QUERY, который может быть дорогой, если T имеет много строк. Не уверен, что курсоры имеют аналогичные накладные расходы. Поэтому я действительно не знаю, с чего начать.

РЕДАКТИРОВАТЬ: Я сделал ошибку, задав два вопроса. Пожалуйста, игнорируйте первое о гарантиях. - Я понимаю, что таких гарантий нет, мне просто было любопытно, что именно может вызвать проблемы в PostgreSQL, поскольку я не знаком с этой системой.

Чтобы прояснить пример использования: я планирую помещать данные во внешние файлы только для чтения, например CSV, доступные через сторонние таблицы, где я полностью контролирую порядок сканирования. Думайте об этом как о некотором архиве данных.

В: Можно ли написать пользовательскую функцию в PostgreSQL, которая обрабатывает один курсор (Пример 1) или два курсора (Пример 2) и строки «сращивания» испускается при двух последовательных сканированиях на стороне сервера?

1 Ответ

0 голосов
/ 04 февраля 2020

Это не будет работать. Порядок результатов оператора SQL является переменной без ORDER BY:

  • Каждое UPDATE изменит физическое местоположение строки таблицы.

  • Нет гарантии того, что INSERT произойдет в конце таблицы.

  • Даже если нет никаких изменений, последовательное сканирование не всегда начинается с начала .

Единственный способ заставить его работать, если вы заполняете данные в пустой таблице в правильном порядке, никогда больше не изменяете таблицу и устанавливаете synchronous_seqscan в off, но я думаю, это не то, что вы хотите сделать.

Я думаю, ваша идея - преждевременная оптимизация, и вы должны создать внешний ключ и присоединиться так, как этого хотел Кодд. В качестве альтернативы, если вашей основной проблемой является очень много столбцов, возможно, вы можете объединить менее важные атрибуты вместе в столбец jsonb, который PostgreSQL может хранить вне строки в таблице TOAST, если он становится слишком большим.

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