Pull to refresh

Comments 56

зарплату DBA Oracle после этого урезали или нет? Плюшки какие от этого переезда вам?
Зарплату, конечно, не урезали. В этом нет смысла, наши DBA активно участвуют в миграции и осваивают PSQL. А вот про плюшки можно долго говорить. Их много. Во-первых, это банальная экономия. Oracle очень дорогой и в стоимости лицензий, и в поддержке. Тарифицируется в долларах, скидки дает в единицах процентов. Во-вторых, для нас крайне актуально легкость в поднятии новых баз с учетом микро-сервисной модели, обилия тестовых стендов и необходимости, порой, иметь локальную БД на разработческом ноутбуке. Тут с PSQL все сильно проще. В-третьих, за счет лицензии open source и сообщества к PSQL достаточно быстро делают необходимый в администрировании и эксплуатации инструментарий. И он так же бесплатный.
А почему раньше был выбран oracle (и при этом не использовался хранимый PL/SQL код)?

Oracle был выбран исторически — системе 15 лет и речь идет о сервисе, который был с самого появления системы. Что тогда было критерием выбора — уже сложно точно узнать :)
Хранение логики в БД противоречит нашим принципам поддержки масштабирования и тестирования кода. Базам отводится только роль простых хранилищ с легкими операциями чтений, записи и обновлений. Максимум логики на клиенте.
А после миграции легкость операций на ваших объемах и операциях в какую сторону изменилась?

Тут я могу сказать, что без оптимизаций выдачи в профиле истории операций, мы получили заметную деградацию. Но после нескольких быстрых доработок окончательная производительность просела относительно Oracle примерно на 10-15%. Сейчас смотрим что можно сделать в плане следующей волны оптимизации, которая должна дать прирост порядка 30%. При этом, за счет отказа от переноса старых таблиц, дефрагментации и сжатия BLOB, мы в PostrgreSQL получили экономию дискового пространства порядка 40% относительно Oracle.
«старые таблицы» это как… они нигде уже не используются и в оракле им забыли сказать drop?

Все верно — сервис очень живой: постоянно добавляется и удаляется логика, связанная с профилем.
Что-то взлетает и остается навсегда, а что-то отмирает со временем и остается как рудимент.
При миграции смотрели на нагрузку на таблицу в БД и на использование в коде.

К слову, на старте было 70, а не 50 таблиц.
Но, к сожалению разработчиков самые сложные таблицы для миграции в этот список не попали :)
А как вы примерно 30% рассчитали?
В принципе, эта статья и комментарии к ней — это все, что нужно знать о квалификации как старой, так и новой команды яндекс-денег.

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

А для каких данных использовали blob'ы, да еще и в таком количестве?
Все неструктурированные данные, которые нельзя красиво уместить в реляционную модель:
— входные параметры платежа
— описание состояния платежа (контексты операций)
— результат платежа
— кастомные параметры профиля пользователя

Размер LOB у нас обычно варьируется от 1 до 8 Кб на одну строку.

Не лучше ли подобные данные хранить в json(b) или xml? Или они настолько неструктурированы, что овчинка выделки не стоит?

Да вы почитайте внимательнее. Они переносили таблицы по одной. Понимаете? Т.е. у них даже джойны из разных таблиц в приложении. Из разных таблиц РСУБД! Из Оракла, карл! Ну как так-то? Это же настолько наколеночная поделка, что тут даже «разработчики», уверенные, что из каких-то там запросов данные поступают в некоем порядке, уже абсолютно естественны.
Меня больше удивляет вот что. Если их купил СБ, то почему не послал людей из СБТ посмотреть, на чем крутится купленная поделка? В СБТ уйма грамотного народа. После заключения СБТ этих самодельщиков просто бы по-тихому разогнали и переписали бы все по-человечески, все-таки деньги. Где внутренний аудит СБ?
Как уже отмечалось в комментариях, разные сценарии миграции требуют разных подходов. В статье описана конкретная методика на примере одного типа таблиц, для которого целесообразен был именно описанный вариант.
Разумеется, переключение связанных таблиц происходило одновременно, с учетом явной связи в БД — join и неявной — по коду.
Что касается логики в БД, то мы принципиально против такого подхода в своей системе.

Oracle хороший мощный инструмент. Особенности нашей работы не позволяют использовать все его возможности. Нам важны производительность сервиса, утилизация железа, возможность дешевого масштабирования и применение автоматического тестирования.
Все это зачастую закрывает для нас такие теоретические подходы как нормальная форма, логические связи в бд и даже внешние ключи.

В процессе миграции часть из 50 таблиц работала на Oracle, другая — на PoPostgreSQL

То есть таблицы, которые в запросах join'ятся, переносились вместе? А что если большинство таблиц друг с другом соединяются во многих запросах, как бы тогда выглядел сценарий переноса? Это вроде бы нормальная ситуация для нормализованной базы

Кроме бага pgjdbc и выкладывания oracle-to-postgres-migration-utils улучшали какие -либо opensource решения? (отправляли ли патчи, заводили ли баги)
С точки зрения Postgres хватило текущей функциональности и документации.
А вот по SymmetricDS потребовалась помощь их саппорта.
так как в Oracle отсутствие признака означает вывод в хронологическом порядке.
Об этом как-то упомянуто в документации? Насколько мне известно, отсутствие order by означает только одно — то что сервер имеет право вывести данные в любом порядке. Один раз я даже на это крупно напоролся. На Oracle.
В тексте статьи проблема описана неточно.
Суть проблемы — если запросе есть limit, то планировщик Postgres решает, что ему дешевле искать полным перебором.
В итоге получаем full scan, несмотря на наличие индекса.
Oracle в запросах с limit корректно использует индекс.

Лечится проблема в Postgres:
• либо оборачиванием запроса в set enable_seqscan to off; set enable_seqscan to on;
• либо сортировкой (order by) по полю, для которого есть индекс.

Ссылки по теме:
1) https://www.postgresql.org
2) stackoverflow
Не сочтите меня занудой, но в Oracle нет фразы "limit" (есть rownum, но он с причудами).
Суть моего комментария не в том, что в PostgreSQL нельзя рассчитывать на порядок выборки без order by, а в том, что и в Oracle этого нельзя делать! Никогда! Даже если, по каким-то причинам (например из за наличия в запросе группировки), оптимизатор выбирает план, приводящий к выводу строк в требуемом (например «хронологическом») порядке, никак нельзя рассчитывать на то, что он будет использовать этот план всегда. В какой-то момент план изменится и вся логика, завязанная на порядок выборки строк сломается! И невозможно сказать, в какой момент это произойдёт! Если вам требуется порядок выборки — используйте order by.
Все верно.
Без явного указания order by надеяться, что порядок данных всегда будет одним и тем же, крайне оптимистично.
Я бы уточнил — абсолютно профнепригодно. Давайте называть вещи своими именами.
Поясню с чем мы столкнулись на примере.

На Oracle запрос выглядел вот так:
SELECT EVENT_ID, EVENT_TYPE 
FROM EVENT
WHERE EVENT_DATE < :eventDate AND ROWNUM = 1 FOR UPDATE SKIP LOCKED

Для Postgres мы переписали его вот так:
SELECT EVENT_ID, EVENT_TYPE 
FROM EVENT
WHERE EVENT_DATE < :eventDate FOR UPDATE SKIP LOCKED LIMIT 1

И поняли, что получили нереально большую просадку по производительности.
При этом количество записей, которые попадали под условие EVENT_DATE < :eventDate было небольшим — десятки.

Посмотрели план запроса:
postgres@demo:5432 (demo-service) # explain (analyze,buffers) 
SELECT EVENT_ID, EVENT_TYPE FROM EVENT WHERE EVENT_DATE < now() + '30 day' limit 100;
                                    QUERY PLAN                                                           
-----------------------------------------------------------------------------------------------
Limit  (cost=0.00..59.53 rows=100 width=18) (actual time=0.022..0.817 rows=100 loops=1)
   Buffers: shared hit=20
   ->  Seq Scan on event  (cost=0.00..154329.33 rows=559239 width=18) (actual time=0.022..0.807 rows=100 loops=1)

Индекс по EVENT_DATE есть, но видно, что Postgres его не использует и выполняется Seq Scan.

Лечение заключается в прямом указании Postgres на использование нужного индекса путем добавления сортировки, которая не требуется с точки зрения бизнес-логики клиента:
SELECT EVENT_ID, EVENT_TYPE
FROM EVENT
WHERE EVENT_DATE < $1 order by EVENT_DATE FOR UPDATE SKIP LOCKED limit 1

В итоге получаем Index Scan:
postgres@demo:5432 (demo-service) # explain (analyze,buffers)
SELECT EVENT_ID, EVENT_TYPE FROM EVENT WHERE EVENT_DATE < now() + '30 day' order by EVENT_DATE limit 100;
                                     QUERY PLAN                                                                              
-----------------------------------------------------------------------------------------------
Limit  (cost=0.44..87.03 rows=100 width=26) (actual time=0.061..183.099 rows=100 loops=1)
   Buffers: shared hit=28 read=89
   I/O Timings: read=182.489
   ->  Index Scan using event_idx1 on event  (cost=0.44..205111.55 rows=559239 width=26) (actual time=0.060..183.057 rows=100 loops=1)
         Index Cond: (event_date < (now() + '30 days'::interval))
         Buffers: shared hit=28 read=89
         I/O Timings: read=182.489
Planning time: 0.301 ms
Execution time: 183.175 ms
А, магия skip locked и волшебные индексы Oracle.
Это конечно немного другая история, согласен.
а LIMIT 1 с order by в PG точно работает аналогично по
приоритетам как и в Oracle ROWNUM = 1 c order by?

странный способ стабилизации плана выполнения — уж лучше запрещенные хины в Oracle


Что значит "запрещенные" хинты, кто их успел запретить? :)

WHERE EVENT_DATE < :eventDate AND ROWNUM = 1
Никогда не пишите так в Oracle.
не вижу криминала. поясните?
http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html
Лечение заключается в прямом указании Postgres на использование нужного индекса путем добавления сортировки, которая не требуется с точки зрения бизнес-логики клиента:

Silron, т.е. вам нужны случайные записи?
Я бы еще добавил, что дело может быть даже не в плане, а в версии oracle.
недавно столкнулись, что выборка
select * from (
select * from ...
order by ...
)
where rownum<10;

на 12.1 стала иногда выдавать результаты не в порядку внутреннего order by, хотя план запроса не не изменился.
Пришлось добавлять внешний order by.
Господь/ЛММ/провидение, храни и размножай дальше таких работничков, как эти топикстартеры, ибо пока они каким-то образом пробираются на продакшн и показывают себя, на нас всегда будут молиться работодатели как на последнюю надежду, данную свыше.
А как вы сейчас считаете, стоило делать такую сложную схему или все же можно было остановить сервис на некоторое время и перенести часть таблиц? Например сделать несколько таких итераций, поделив их по времени. Т.е. например перенести справочники целиком. А операции по частям, например по годам или кварталам?

Если НСИ потребуют остановки, то наверное, большую часть операций, можно перегрузить «в фоне».
Яндекс.Деньги — финансовый сервис, и минута простоя стоит достаточно, чтобы избегать простоев :) Например, переводили как-то сервис работы с магазинами. И там был нюанс в том, что БД маленькая и владельцы магазинов обычно спят по ночам. Поэтому ту миграцию выполняли ночью с простоем 25 минут — сценарий миграции может отличаться в зависимости от условий.
Что касается описанной в статье ситуации, то мы и перегружали данные в фоне, а потом делали обновления в обе БД. И только после этого выполняли переключение
Спасибо. Очень бы потом хотелось бы увидеть к-либо данные по фактической производительности. Как по факту выросли или упали требования к производительности.

Все же такой опыт поможет сломать недоверие некоторых заказчиков к опен-сорс ПО.

В любом случае результат будет у каждого свой, так как во-первых у Яндекса могут оказаться какие-то специфичные требования к БД, которых не будет в другом проекте, и наоборот. Так что основной вопрос так и останется к применимости того или иного инструмента(в данном случае СУБД) под использование в конкретной задаче.
Это понятно. Но тут речь о другом. О самой возможности заменить в очень крупной компании, Оракл, который работает в 24*7 с критическими финансовыми данными, на Постгрес.

Т.е. это определенное доверие опен-сорс продукту.

Мне вот сложно обосновать, почему заказчик может использовать Постгрес, а не, например, mssql. Точнее обосновать то я могу. Но доверие берется как раз на примере таких переходов.

По сути вы использовали обычные техники zero downtime deployment для деплоев с изменением схем баз данных, с тем лишь нюансом, что новая и старая схема оказались на разных СУБД?

Важно, что меняется не только БД, но и её тип. А значит нужен код, который может одновременно работать с двумя типами БД.
Учитывая что код разрабатывался годами и разными людьми, такая миграция представляет ещё большой риск.
И наша статья про то, как давно живущее приложение аккуратно перенести в сжатый срок на новое окружение с полной миграцией всех данных без прерывания процесса.

Понятно, что нужна дополнительная обвязка в коде, но логически, по-моему, код, который работает одновременно с двумя БД одного типа не сильно отличается от кода, который работает с двумя БД разного (но идеологически схожего) типа. Задача переноса без даунтайма с БД одного типа на БД другого типа, конечно, сложнее, но пока не доходит до специфических команд, то концептуально она не сильно отличается от переноса между двумя БД одного типа, если не пользоваться встроенными инструментами СУБД для этого. Те же принципы, основной из которых, то, что код клиента при переходе модифицируется поэтапно:


  • читаем из старой, пишем в старую (исходная точка)
  • читаем из старой, пишем в обе
  • читаем из новой, пишем в обе (необязательный в целом шаг, но уменьшает риски)
  • читаем из новой, пишем в новую (конечная точка)
Для основной массы таблиц использовался более простой, надежный и дешевый способ миграции через SymmetricDS. В конце проекта «легкие» таблицы кончились и последние 1.5 месяца мы потратили на ручную миграцию через специально написанные очереди миграции данных. Такой подход требует больше ресурсов на разработку и внимательного тестирования.
По аналогии с SymmetricDS, очередь выполняла не только синхронизацию новых и измененных данных, но и начальную массовую загрузку исторических данных в батч режиме.

Особенно важно при работе с критичными таблицами для нас было иметь возможность отката на Oracle без потери данных после переключения на Postgres. Несколько раз мы воспользовались этой функциональностью, когда Postgres не вытянул нагрузку и пришлось переключаться обратно, до решения проблемы.

SymmetricDS мощная штука. Мы на нём ДВХ начали делать.


Вы опенсорс версией пользовались или покупали полный комплект инструментария и поддержки? Там, помнится, тысячи долларов за год.

Интересный опыт. Тоже планируем переход на постгрес (только с MS SQL). И спасибо за подборку инструментов миграции.
А если не секрет в чем причина переезда? У нас наоборот произошло с постгреса на azure sql. Цена конечно дикая, но производительность на первый взгляд выше
Лет 10 назад пришлось столкнутся с оракл грид. Там была просто дикая производительность на обычном железе. Правда на продакшн не взлетело, но это по причине желаний заказчика.
С azure сервисами такая же штука, все очень быстро из «коробки», но надо быть gold партнером чтобы пользоваться этими благами по причине диких цен. Я вообще непредставляю заказчика, который согласился бы добровольно за это платить.
С чем связан отказ от MS SQL, если лицензия уже есть? Только не говорите «импортозамещение».

P.S. Чувствую в РФ скоро будет больше запросов о миграции, чем когда-либо, так что статья в тему сегодняшнего дня.
Какие альтернативные сценарии переноса данных рассматривали? Для меня перенос по таблицам большая экзотика. Предпочитаю перенос всех ретро данных, а топом горячих. Например, за последний час. При этом остановка длится 1-2 минуты, что не критично для большинства сервисов.
Не знаю, насколько связана миграция БД с тем, что происходит с платежами ЯД сейчас. А сейчас (и ровно то же самое было замечено в начале апреля) ситуация такова:
Пытаюсь отправить деньги через форму-приниматель на сайте, и если платеж осуществляется с карты, то в 90% случаях получаю ошибку. Ошибки различные, от чего зависит — непонятно.
Платежи делал с разных карт разных банков. На разные счета в Яндексе.
Причем платеж Яндекс-деньгами всегда проходит, проблема только при платеже картой.
Опять же, при платеже не через форму-приниматель на Яндекс-кошелек, а через Яндекс-кассу юрлицу платежи картой проходят нормально.
Две наиболее часто встречающихся ошибки
image
image

Эти две пореже, но тоже имеют место
image
image

Около двух лет пользуюсь формой яндекса на сайте, ранее проблем не было.
Да тут весь топик этот с комментами от топикстартеров просто кричат, до чего же эти горе-писатели не понимают самых основ sql. Не понимают даже, как гарантировать требуемую сортировку, что само по себе дико. Как результат, в продакшене это приводит к плавающим трудноотлавливаемым ошибкам. Пять раз на тесте отработало (и в продакшн (с)), потом десять раз через десять на проде. Когда им тут же явно указывают, что именно у них не так и как надо — у них бомбит, но ни слова из написанного до них не доходит. Квалификация, чего вы хотите.
Здравствуйте! Да, неприятный опыт какой-то… Не могли бы вы скинуть свои контакты мне в ЛС? Перешлю техподдержке для изучения проблемы.
Sign up to leave a comment.