Меня зовут Максим Грамин, я давно работаю с базами данных в разных ролях и собираю разные полезные инструменты в awesome-листе (если не обнаружите свой любимый инструмент, приносите, я буду признателен).

Эта статья написана по мотивам моего доклада на PGConf.Russia 2025, в котором я рассказал о том, что такое ненастоящие (или фейковые) данные и для чего они нужны.

Ненастоящие данные

Самый простой пример ненастоящих данных — списки экземплификантов, которые обычно используют в тестовых средах. Реальные данные в такие системы не вносят и получается что-то такое:

Помимо неэстетичного вида, у данных в таблице выше могут быть проблемы с валидаторами (если они есть в базе данных), бизнес-логикой и уникальностью. 

Можно сгенерировать такой же набор колонок с ФИО, должностью и адресом, но выглядеть он будет солиднее:

Данные из таблицы выше абсолютно безопасны: все ФИО и адреса в ней вымышлены. О том, как сгенерировать фейковые данные, мы и поговорим.

Для чего нужны ненастоящие данные

Фейковые данные могут пригодиться:

  • для функционального тестирования: можно сгенерировать большой набор самых разных данных и посмотреть, обнаружатся ли в системе ошибки и несоответствия, как сработают триггеры и ограничения;

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

Такие данные будут абсолютно безопасны, их можно передавать подрядчикам, демонстрировать коллегам, руководству, заказчикам, партнёрам.

Как сгенерировать «подделку»

Тестовые данные можно получить четырьмя способами:

1. Маскирование

Если вам нужно превратить в тестовую среду продакшен-базу данных, которая содержит чувствительные данные, проще всего намеренно их испортить — замаскировать. При этом определённые свойства, например, количество строк и контрольные суммы, сохранятся. В итоге вы получите готовую безопасную среду.

Маскирование данных
Маскирование данных

2. Генерация с нуля

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

Генерация с нуля
Генерация с нуля

3. Интерполяция данных

Если некоторые данные уже есть, а вы хотите узнать, какими они будут в перспективе, можно интерполировать данные. Например, вас может заинтересовать, какие данные будут через год в приложении, которое только что запустили, и справится ли система с таким объёмом.

Интерполяция данных
Интерполяция данных

4. Комбинация предыдущих сценариев

Последний и самый популярный сценарий — комбинация всех предыдущих.

Комбинирование
Комбинирование

Способы «испортить» данные

Рассмотрим три основных способа:

  1. Написать скрипт на SQL или другом языке. Можно использовать Python Faker или другие фейкеры или их обёртки под PostgreSQL (PostgreSQL Faker, Faker FDW). Подходит для одной или нескольких схем, которые не очень часто меняются.

  2. Опенсорсные комбайны, которые сканируют вашу базу данных, извлекают конфигурационные файлы со сценариями и выдают результат. Примеры: GreenMask, PostgreSQL Anonymizer (его можно отнести и к первой группе, потому что он имеет отдельные функции, которые можно использовать в скриптах, и стратегии для таблиц) и разработки компании Snaplet.

  3. Test Data Manager, или фабрики по производству тестовых сред. На вход могут принимать любую базу данных, источники данных из веб-сервисов и плоских файлов, а на выходе создать целую среду, например, в облаке. Примеры: Tonic, Gretel, Delphix и Informatica TDM.

Все эти инструменты имеют общие паттерны (fake data patterns), о которых мы сейчас и поговорим.

Паттерны маскировки

Статическое маскирование

Статическое маскирование — это замена чувствительных данных статической строкой с частичным или полным сохранением длины или без сохранения вовсе. Например, в последней колонке мы частично замаскировали имейл и сохранили его формат.

Статическое маскирование
Статическое маскирование

Плюс: таким способом можно скрыть данные подручными средствами.

Минусы: такие данные не должны попадать в ключи, потому что тогда ссылки не создадутся. Данные не должны содержать индексов, валидаторов, проверок и бизнес-логики.

2. Хеширование

Захешировать строчку можно с помощью стандартных постгрессовых функций. Хеш придется обрезать по длине колонки или исходного значения.

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

Хеширование
Хеширование

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

Другие паттерны

  • Зашумление (noising) — подмешивает в значения шум.

  • Генерализация (generalization) — подставляют диапазон вместо конкретного числа. Например, зарплата не 100 долларов, а от 0 до 200.

  • Агрегация (aggregation) — заменяет все значения средним или другим агрегатом (максимумом, минимумом). 

  • Маскировщики на основе правил (сonditional/rule based masking) — маскируют по заданной логике или бизнес-правилам. Например, не показывать названия фильмов с возрастным ограничением 18+.

  • Шафлинг (shuffling) — перемешивают значения внутри колонки, не меняя самих значений.

  • Маскирование структурированных данных (JSON, XML, текстовых, бинарных) — маскирует все значения, или значения вместе с ключами, или значения по ключу. 

  • Рандомизированный маскинг (randomized masking) — маскирует значение другим рандомным значением.

Паттерны генерации

Обычная генерация

Самый простой способ — генерация строк (например, с ФИО и датами) с помощью GenerateSeries. Годится, чтобы быстро заполнить таблицу, посмотреть, как она работает и какие особенности имеет, запустить на ней приложение или отчёт.

Вот пример несогласованной (спонтанной, без правил) генерации — колонки name и email здесь не согласованы.

Несогласованная генерация
Несогласованная генерация

Продвинутая генерация

Вот пример согласованной генерации, когда данные в колонках пересекаются по определённому правилу.

Согласованная генерация
Согласованная генерация

Генерация по ключу

Допустим, у вас есть родительские таблицы, например, фильмы и актеры, из которых нужно сгенерировать набор, кто в каких фильмах снимается.

Первый подход — создать математическое правило. Пусть, например, в каждом фильме снимается три случайных актера (как на скриншоте) или от двух до десяти.

Второй подход — использовать распределение вероятностей, которое отвечает заданным правилам. Пусть, например, в кассовых фильмах снимаются популярные актеры, а в недорогих — не очень известные.

Циклы

Циклы помогут, если таблица замыкается на себе.

Сначала нужно разобраться в сущностях таблицы с точки зрения части бизнеса: есть сотрудники и менеджеры, у каждого сотрудника есть руководитель — и выстроить иерархию должностей, которой должны отвечать генерируемые данные.

В новой структуре не будет циклической связи, и для каждой сущности можно сгенерировать плоские запросы, обычные инсерты с помощью PostgreSQL Faker, например.

При выборе инструмента смотрите, как он будет такие ситуации разрешать, какие имеет ручки и обходы.

Ключ к успеху любого маскирования, генерации данных, подготовке тестовых сред в том, чтобы хорошо знать схему базы данных. Порой нужно придумывать обходы — следите, чтобы ваш инструмент или скрипт разрешал обрабатывать только части таблиц. Есть ещё триггеры и хранимые процедуры, которые могут влиять на те данные, которые вы генерируете или маскируете — помните об этом.

Kick start

  1. Тщательно изучите схему баз данных.

  2. Подберите подходящий инструмент генерации.

  3. Создайте тестовую среду, сгенерируйте данные, замаскируйте их на базовом уровне и покажите коллегам.

Комментарии (0)