Мы же не пытаемся обеспечить там zero-downtime, верно? И вообще, зачем пытаться запускать окружение разработчика на кластере и за балансировщиком нагрузки?
Конечно, нет. Но мы пытаемся сделать процесс разработки удобным и безопасным не только в контексте выкатки на прод, но и для разработчиков, верно?
Поймите меня правильно, я не оцениваю предлагаемый вами подход как правильный или неправильный, а хочу понять как он в целом работает на практике.
"Auto-migration on startup" - это одна из стратегий. Есть еще режим "Validate", который сверяет миграции в приложении с теми, что были применены в БД. Это позволяет, например, реализовать схему, когда один экземпляр приложения отвечает за накатку миграций, а остальные делают только валидацию.
При использовании CI/CD сервера для накатки миграций каким образом накатывать их на локальные окружения разработчиков?
Одно из удобств упомянутых ранее инструментов вроде flyway и liquibase, а если быть точнее в целом стратегии обновления схемы через приложение, в том, что процесс одинаков для всех окружений - где бы приложение не запустилось, оно либо обновит схему до нужной версии, либо упадет, сообщив, что схема несовместима.
Помимо отсутствия индекса history_b_results(history_b_id), не понятно для чего разбивать таблицу на две - можно в history_b_results добавить customer_uuid и не делать JOIN. Но возможно, что в реальности есть какие-то доп. детали, которые опущены в примере.
У вас результаты исходного и оптимизированного запросов отличаются. Исходный запрос сперва делает join, а потом sum, а второй сперва sum, а потом DISTINCT, из-за чего сумма в 8 раз больше. До:
В добавление к ответу выше – если ограничение/индекс не включает ключ партиционирования, но при этом «глобальная» уникальность требуется, есть костыльный вариант создать триггер на модифицации для валидации. Но это будет сильно влиять на производительность обновлений.
Согласитесь, что ключи и индексы — это совершенно разные вещи. Ключи обеспечивают целостность и непротиворечивость данных с точки зрения бизнес правил, в то время как индексы — это чисто техническая вещь для ускорения доступа к данным.
Полностью согласен с вами и сам лично также предпочитаю выполнять этот последний «опциональный» пункт по созданию ограничения на основе индекса.
Более того, как я отметил в статье, раньше даже сама документация советовала использовать ограничение, а вот почему с 9.5 эту сноску удалили – интересный вопрос.
Да, возможно, что statement_timeout даже более безопасно использовать, т.к. включает и время захвата блокировки и ее удержание во время выполения команды.
С EXCLUDE мне не особо приходилось работать, поэтому ничего не написал :-) Если есть, чем поделиться, то так же буду рад дополнить статью.
Спасибо за подробный комментарий! Дополню статью.
Небольшой вопрос – в какую из минорных версий pg12 попал ваш патч (беглый поиск по release notes не помог мне)?
Спасибо!
Кстати, для того, чтобы быстро откатывать вашу базу в начальное состояние вы можете посмотреть в сторону «тонкого клонирования» — быстрое создание копии файловой системы на основе ZFS. Есть даже более менее готовое решение — Database Lab. Сам я его на практике не пробовал, но вероятно, мы будем рассматривать его как один из вариантов для реализации т.н. «иммутабельных» тестовых сред (когда на каждый запуск набора e2e тестов создается новая база с подготовленными тестовыми данными).
Я согласен с вами — тестовые данные нужны только для тестов и располагать их в общих миграциях будет неправильно. С другой стороны, если для тестов также хочется иметь версионность (т.е. для разных версий схемы данных разные тестовые наборы, а не только тесты для последней версии), то можно вести отдельную систему миграций. Примерно так:
Основные миграции:
V1_create_table1.sql
V2_alter_table1.sql
V3_create_table2.sql
Тестовые миграции:
V1_create_test_data_table1.sql
V2_create_test_data_table1.sql
V3_create_test_data_table2.sql
А при запуске тестов в зависимости от версии схемы данных накатывать на базу соответствующую миграцию с данными.
Не очень понимаю, когда это может быть нужно, но теоретически, наверное, имеет право на жизнь :-)
Интеграционных тестов примерно 2 тысячи, выполняются около 5-7 минут.
Не удалось ли вам с подготовкой образа как-то примонтировать tmpfs (может быть, копированием data dir через init.sh в образе)?
Сконцентрировавшись на проблеме прогона миграций на запуске каждого тестового класса, мы почему-то даже не посмотрели в эту сторону, но выглядит перспективно, попробую — спасибо за идею и за вашу заметку!
Кажется, что с картинкой что-то не так:
в глаза сразу бросается, что сумма за 2021 год больше 100% (привет Чурову)
числа не очень совпадают с оригинальным исследованием:
Для UnionPay: 40.03 - 1.39 = 38.64% в 2021 и 40.03% в 2022
Для Visa: 38.78 + 0.82 = 39.6% и 38.78%
Mastercard: 21.19 + 0.57 = 21.76% и 21.19%
Также не очень понятно откуда взялось вот это (не нашел в оригинале):
Спасибо! К сожалению, мой опыт работы с другими РСУБД значительно меньше, поэтому не смогу сделать качественный анализ.
В 3 режимах - есть ещё statement.
Конечно, нет. Но мы пытаемся сделать процесс разработки удобным и безопасным не только в контексте выкатки на прод, но и для разработчиков, верно?
Поймите меня правильно, я не оцениваю предлагаемый вами подход как правильный или неправильный, а хочу понять как он в целом работает на практике.
промазал ответом
"Auto-migration on startup" - это одна из стратегий. Есть еще режим "Validate", который сверяет миграции в приложении с теми, что были применены в БД. Это позволяет, например, реализовать схему, когда один экземпляр приложения отвечает за накатку миграций, а остальные делают только валидацию.
При использовании CI/CD сервера для накатки миграций каким образом накатывать их на локальные окружения разработчиков?
Одно из удобств упомянутых ранее инструментов вроде flyway и liquibase, а если быть точнее в целом стратегии обновления схемы через приложение, в том, что процесс одинаков для всех окружений - где бы приложение не запустилось, оно либо обновит схему до нужной версии, либо упадет, сообщив, что схема несовместима.
Я не большой эксперт в kubernetes, но вроде как это можно решить с помощью настройки maxUnavailable и maxSurge.
Помимо отсутствия индекса history_b_results(history_b_id), не понятно для чего разбивать таблицу на две - можно в history_b_results добавить customer_uuid и не делать JOIN. Но возможно, что в реальности есть какие-то доп. детали, которые опущены в примере.
У вас результаты исходного и оптимизированного запросов отличаются. Исходный запрос сперва делает join, а потом sum, а второй сперва sum, а потом DISTINCT, из-за чего сумма в 8 раз больше. До:
После:
Полностью согласен с вами и сам лично также предпочитаю выполнять этот последний «опциональный» пункт по созданию ограничения на основе индекса.
Более того, как я отметил в статье, раньше даже сама документация советовала использовать ограничение, а вот почему с 9.5 эту сноску удалили – интересный вопрос.
С EXCLUDE мне не особо приходилось работать, поэтому ничего не написал :-) Если есть, чем поделиться, то так же буду рад дополнить статью.
Насчет остального – спасибо за идеи, подумаю.
Небольшой вопрос – в какую из минорных версий pg12 попал ваш патч (беглый поиск по release notes не помог мне)?
Эксперименты показывают, что уникального индекса все же достаточно. В ссылке на SO выше есть пример для воспроизведения:
Причем, если не создавать индекс, то получим ошибку:
В общем, похоже на неточность в документации.
Кстати, для того, чтобы быстро откатывать вашу базу в начальное состояние вы можете посмотреть в сторону «тонкого клонирования» — быстрое создание копии файловой системы на основе ZFS. Есть даже более менее готовое решение — Database Lab. Сам я его на практике не пробовал, но вероятно, мы будем рассматривать его как один из вариантов для реализации т.н. «иммутабельных» тестовых сред (когда на каждый запуск набора e2e тестов создается новая база с подготовленными тестовыми данными).
Основные миграции:
V1_create_table1.sql
V2_alter_table1.sql
V3_create_table2.sql
Тестовые миграции:
V1_create_test_data_table1.sql
V2_create_test_data_table1.sql
V3_create_test_data_table2.sql
А при запуске тестов в зависимости от версии схемы данных накатывать на базу соответствующую миграцию с данными.
Не очень понимаю, когда это может быть нужно, но теоретически, наверное, имеет право на жизнь :-)
Сконцентрировавшись на проблеме прогона миграций на запуске каждого тестового класса, мы почему-то даже не посмотрели в эту сторону, но выглядит перспективно, попробую — спасибо за идею и за вашу заметку!