Comments 28
Давно уже занимаюсь переводом на постгрю. Самое веселое было, когда нам дали Экзадату (оракл на стероидах) и попросили перевести на постгрю. Экзадата хороша тем, что можно быть нубом в sql, не знать, что существуют планы запросов и получать неимоверные быстрые селекты с группировками и прочим. Так вот, нам пришлось перелопачивать абсолютно каждый из нескольких сотен запросов, чтобы это хоть как-то крутилось на постгре. Стоимости лицензий и специального железа ушли, но возникла потребность в классных базистах.
Добрый вечер!
Своё карьеру я начинал PL/SQL разработчиком. В моём случае, нужно было знать как можно больше про планы выполнения и про приёмы написания хорошего SQL-кода.
Мне также доводилось конвертировать запросы из exadata в СУБД PostgreSQL на одном из пилотных проектов. Там было над чем подумать, в том числе и над оптимальной схемой секционирования.
Правда, все запросы очень на OLAP были похожи хотя бы потому, что пришлось работать с сотнями миллионов строк.
Такие запросы можно сконвертировать в СУБД PostgreSQL, но запускать их стоит на асинхронной реплике с выключенным hot_standby_feedback и с max_standby_streaming_delay в -1.
Возможно, что в exadata есть свои продвинутые алгоритмы, но, к сожалению, это чёрный ящик, нельзя посмотреть, что там используется.
На самом деле, важно понимать, в каких случаях отчёты стоит выполнять на OLTP-базе, а в каких стоит использовать другие решения.
Если не секрет, какие особенности exadata использовались на проекте? И как сейчас живётся без них в PG?
Заранее спасибо.
Большое спасибо за статью.
Но Вы ничего не сказали, что делать с Oracle Advanced Queuing и Advanced Compression.
Что же делать с объектными типами PL/SQL, если они содержат еще и методы, а не только атрибуты?
Что делать с глобальными контекстами?
И куда засунуть в PG Oracle Flashback Archive?
Добрый вечер!
На часть вопросов ответ дан во 2-ой и 3-ей части цикла.
Oracle Advanced Queuing - секция "Использование механизма очередей", статья https://habr.com/ru/company/postgrespro/blog/683748/
В настоящий момент компрессия есть в СУБД Postgres Pro Enterprise, но там данные сжимаются целиком, если создать табличное пространство с опцией WITH (compression=true)
https://postgrespro.ru/docs/enterprise/14/cfs-usage
Объектные типы PL/SQL с методами - секция "Использование PL/SQL коллекций и объектов", статья https://habr.com/ru/company/postgrespro/blog/683748/
Глобальные контексты - секция "Расширение pg_variables", статья https://habr.com/ru/company/postgrespro/blog/679808/
Flashback, к сожалению, в PG отсутствует из-за того, что не хранится история об активных транзакциях в тот или иной момент времени в прошлом. Об этом подробно рассказывается, в частности, на курсе DBA-2 в лекции "Снимки данных"
https://edu.postgrespro.ru/dba2/dba2_03_mvcc_snapshots.pdf
Также об этом говорится в книге "PostgreSQL изнутри"
https://postgrespro.ru/education/books/internals
Спасибо!
Но pg_varibales НЕ позволяет создать константу существующую для нескольких сессий.
Глобальные константы существуют в оракле в SGA - видимы сразу для всех сессий.
Как это реализовать в PG?
Часть кейсов можно заменить immutable функциями : хранят и оченьбыстро отдают значения, меняются execute
Добрый день!
В данном случае, возможно, придётся вносить изменения в pg_variables так, чтобы данные хранились в общей памяти, только так они будут видны всем сессиям.
а pg_variables имеет опцию а-ля "глобальный / сессионный контекст" ?
Добрый день!
В настоящее время только сессионный.
значит pg_variables умеет в глобально видимую память? только как-то без этой опции?
Пока не умеет.
Модуль pg_variables
содержит функции для работы с переменными различных типов. Созданные переменные существуют в течение текущей пользовательской сессии.
https://postgrespro.ru/docs/postgrespro/14/pg-variables
ну если нужен глобальный, то вот тогда вариант с иммутабл,
вполне схоже по производительности с вызовом переменной из пакета, хоть и не так прозрачно выглядит, и нет удобной автоматизации в виде [пере-]инициации значений в теле пакета при его перекомпиляции
В простом случае, да, immutable-функции помогают, но может быть случай, когда что-то вычисляется, помещается в переменную глобального контекста, а потом другой процесс из этой переменной достаёт значение и использует в своих расчётах
придётся execute -> commit делать при обновлении значения, возможно, одним из аналогов автономной транзакции, тогда другой процесс увидит новое значение
Не подскажете, какие есть подходы к тому, что в PostgreSQL нет глобальных индексов?
Я пока вижу только вариант иметь «глобальную» таблицу вместо индекса, и поддерживать её из кода. Есть ли ещё какие-то опции?
Отличная серия статей. Есть ли что-то похожее на переезд с MS SQL на Pg?
Добрый день!
Oracle. Там при одновременном выполнении нескольких команд MERGE возможно появление дубликатов, что приводит к нарушениям ограничений первичного ключа
Откуда такая информация? Можно ссылки?
Добрый вечер!
Пусть имеется следующая таблица в СУБД Oracle:
CREATE TABLE merge_test(
id NUMBER NOT NULL,
value VARCHAR2(10),
CONSTRAINT PK_MERGE_TEST PRIMARY KEY (id)
);
Пусть к ней обращаются две сессии с autocommit = off следующим образом:
Первая сессия:
MERGE INTO merge_test d
USING (SELECT 1 id, 'A' value
FROM dual
) s
ON (d.id = s.id)
WHEN matched THEN
UPDATE SET d.value = s.value
WHEN not matched THEN
INSERT (d.id, d.value) VALUES (s.id, s.value);
Вторая сессия выполняет запрос ниже, ждёт освобождения блокировки:
MERGE INTO merge_test d
USING (SELECT 1 id, 'B' value
FROM dual
) s
ON (d.id = s.id)
WHEN matched THEN
UPDATE SET d.value = s.value
WHEN not matched THEN
INSERT (d.id, d.value) VALUES (s.id, s.value);
Первая сессия делает COMMIT, а во второй сессии запрос завершается с ошибкой:
Error report -
ORA-00001: нарушено ограничение уникальности (CISADM.PK_MERGE_TEST)
А теперь посмотрим на аналогичную ситуацию в СУБД PostgreSQL. Ниже приведена команда создания таблицы:
CREATE TABLE merge_test (
id bigint NOT NULL,
value VARCHAR(10),
CONSTRAINT PK_MERGE_TEST PRIMARY KEY (id)
);
Первая сессия:
BEGIN;
INSERT INTO merge_test AS t
SELECT 1, 'A'
ON CONFLICT (id)
DO UPDATE
SET value = EXCLUDED.value
WHERE t.id = EXCLUDED.id;
INSERT 0 1
Вторая сессия ждёт снятия блокировки:
BEGIN;
INSERT INTO merge_test AS t
SELECT 1, 'B'
ON CONFLICT (id)
DO UPDATE
SET value = EXCLUDED.value
WHERE t.id = EXCLUDED.id;
Первая сессия выполняет COMMIT:
COMMIT;
Вторая сессия успешно завершается успешно:
INSERT 0 1
SELECT * FROM merge_test;
id | value
----+-------
1 | B
COMMIT;
Ниже приведено содержимое таблицы:
SELECT * FROM merge_test;
id | value
----+-------
1 | B
Добрый день!
Вопрос был не про то, что в PG сделали MERGE, о чём также написано в статьях.
А про то, что в Oracle могут быть ошибки ограничения целостности первичного ключа при работе нескольких MERGE одновременно.
Попросили привести ссылку, я привёл пример.
Кроме того, не все могут сразу обновиться на новую версию СУБД.
Миграция кода с Oracle на PostgreSQL: особенности и пути обхода, средства конвертации, вспомогательные модули