DataVue управляет платформой данных о потребительском кредитовании: широкие таблицы базы данных с тысячами атрибутов на запись, сотни миллионов записей, а также платформа и клиентский SaaS-слой отчетности, работающие на одном движке. Поскольку данные регулируются, архитектурный вопрос, который для большинства команд остается лишь удобством, здесь становится требованием. DataVue должна точно знать, где обрабатывается каждый фрагмент данных и кем.
DataVue уже использовала SingleStore для своей аналитики. Единственным фрагментом пользовательской логики, для которого не находилось подходящего места, был набор ключей сопоставления, лежащий в основе того, как платформа связывает записи, и Python UDF наконец-то предоставили такое решение.
Структура рабочей нагрузки DataVue
DataVue помогает кредиторам, ипотечным брокерам, автофинансовым организациям и другим финансовым фирмам использовать кредитные и демографические данные для охвата потребителей, склонных к конверсии. На уровне хранения рабочая нагрузка имеет характерную форму:
- Широкие таблицы бюро-типа, содержащие тысячи атрибутов на запись потребителя, охватывающие кредитную историю, поведение и предложения.
Широкие таблицы бюро-типа, содержащие тысячи атрибутов на запись потребителя, охватывающие кредитную историю, поведение и предложения.
- Объем данных в диапазоне нескольких терабайт, растущий по мере подключения новых партнерств с бюро.
Объем данных в диапазоне нескольких терабайт, растущий по мере подключения новых партнерств с бюро.
- Две требовательные рабочие нагрузки на одном движке: сама платформа DataVue и клиентский SaaS-слой отчетности.
Две требовательные рабочие нагрузки на одном движке: сама платформа DataVue и клиентский SaaS-слой отчетности.
В предыдущем стеке на базе MySQL с кэшем Redis эта архитектура начала давать сбои по мере роста компании. Аналитика данных в широких таблицах могла выполняться минутами или дольше, задачи по загрузке растягивались на дни, а практический лимит в около тысячи столбцов на таблицу базы данных вынуждал использовать неудобные обходные пути в схеме.
Переход на SingleStore снял это напряжение. Аналитика, которая раньше занимала минуты, стала выполняться за долю этого времени, типичная загрузка, которая длилась более полутора часов, сократилась до нескольких минут, и команда наконец смогла моделировать свои данные так, как это реально выглядит в бизнесе, не борясь с ограничением по количеству столбцов.
Это дало DataVue движок, достаточно быстрый, чтобы ответить на любой вопрос. Однако сам по себе он не предоставил им чистого способа запускать свою важнейшую пользовательскую логику в масштабе.
Сложная часть: ключи сопоставления в огромных широких таблицах
Работа DataVue зависит от сопоставления. Платформа должна объединять «грязные» списки клиентов с данными бюро, создавать файлы подавления и отслеживать, кто уже совершил конверсию. Точное сопоставление строк не выдерживает столкновения с реальными данными, потому что имена пишутся с ошибками, люди переезжают, а один и тот же адрес появляется в дюжине форматов.
Чтобы поглотить этот шум, команда поддерживает несколько ключей сопоставления. Один из них использует фонетическое кодирование в стиле Soundex, производное от функции, изначально стандартизированной для сопоставления почтовых адресов. Идея проста: взять набор полей имени и адреса, свести их к фонетическому идентификатору и позволить двум записям, описывающим одного и того же человека в одном и том же месте, выстроиться по этому ключу, даже если написание отличается.
Операционная реальность сложнее, чем предполагает алгоритм. Центральная кредитная таблица имеет ширину около четырех тысяч столбцов, а объединения со связанными наборами данных увеличивают эффективную поверхность атрибутов до пяти тысяч. Фонетический ключ вычисляется с помощью UDF для сотен миллионов записей каждый месяц, когда поступает свежий файл из бюро, и снова в меньшем масштабе каждый день — для файлов, которые клиенты загружают для самостоятельного использования.
До появления Python UDF этот фрагмент логики существовал в двух местах одновременно: реализация на Python во внешних пакетных конвейерах и соответствующая хранимая процедура SQL внутри SingleStore. Один алгоритм, две кодовые базы и два повторяющихся расхода.
Первым расходом был рассинхрон. Каждое изменение в версии на Python приходилось вручную переводить на SQL и повторно проверять на реальных данных. Различие в потоке управления, обработке типов или один необработанный крайний случай — это именно то, что остается невидимым, пока не всплывет в отчете о сверке спустя недели.
Вторым была цена запуска тяжелой строковой логики как чистого SQL на основном кластере. Ключ на основе Soundex — самый дорогой из набора, и чтобы завершить ежемесячный запуск в отведенное окно, команде приходилось масштабировать кластер SingleStore в начале каждого месяца и уменьшать его после. Они подбирали размер производственного кластера под несколько дней пиковой нагрузки и платили за границу между внешними заданиями на Python и внутрибазовой процедурой каждый раз, когда данные пересекали ее.
Почему очевидные исправления не подошли
DataVue взвесила три стандартных варианта и отклонила каждый по конкретной причине.
Перенести больше логики в SQL. Нетривиальные бизнес-функции, написанные на SQL, становятся трудными для чтения и еще более трудными для тестирования. Вычисление Soundex — это уже плотный стек выражений case, и чем больше он растет, тем меньше людей готовы его трогать. Кроме того, вы продолжаете платить за эти вычисления на основном кластере, даже если задание выполняется всего несколько дней в месяц.
Запускать Python в отдельном сервисе. Это устраняет дублирование, но выводит большие части регулируемого набора данных за пределы платформы для обработки в другом месте и последующего возврата. Для DataVue это невыгодный обмен: больше учетных данных, больше сетевых путей, больше мониторинга разных стеков и гораздо более сложный ответ, когда аудитор спрашивает, где обрабатывались данные и кем.
Перенести работу на внешнюю платформу признаков или вычислений. Разумно, когда данные уже там находятся. Кредитные таблицы DataVue уже были в SingleStore, поэтому их копирование только добавило бы задержки, затраты на хранение и лишние компоненты, в которых команда не была заинтересована.
То, что нужно было DataVue, было более узким: оставить широкие таблицы в SingleStore, сохранить одну каноническую копию логики ключа в Python UDF и эффективно запускать эту UDF для сотен миллионов записей в рамках ежемесячного пакетного задания.
Что делают Python UDF в SingleStore
Python UDF были созданы именно для такой задачи. Вы пишете обычную функцию на Python, помечаете ее декоратором и позволяете платформе превратить функцию в сервис UDF, который может вызывать SQL. Когда блокнот запускается против базы данных, SingleStore регистрирует Python UDF и запускает небольшой набор контейнеров в том же регионе, что и движок. С этого момента SQL вызывает ее как любую встроенную функцию в каталоге.
Под капотом движок потоково передает входные столбцы, необходимые этим контейнерам, пакетами, собирает результаты и продолжает выполнение запроса. Данные никогда не покидают платформу, и команде не нужно думать о технической реализации.
Для DataVue это было недостающим вариантом: взять реализацию ключа сопоставления на Python, которой команда уже доверяла, и запустить ее внутри платформы данных, а не рядом с ней.
Что изменилось
Одна реализация, один источник истины. Логика генерации ключей теперь находится в единой кодовой базе на Python, на языке, который предпочитает команда, и подкреплена одним набором тестов, независимо от того, вызывается ли она из ежемесячного пакетного задания или специального запроса. Целая категория задач, связанная с трансляцией в SQL и сверкой двух версий с реальными данными, просто исчезла.
Тяжелые вычисления были перенесены с основного кластера без выхода за пределы платформы. Ежемесячный запуск теперь выполняется в автоматически масштабируемых контейнерах, которые существуют только во время вычисления ключей. Движок отвечает за хранение и аналитику, а уровень UDF — за интенсивную обработку строк. Время выполнения ежемесячной генерации ключей сократилось примерно вдвое без постоянного увеличения размера кластера и необходимости масштабировать производственный кластер вверх и вниз в течение нескольких дней пиковой нагрузки.
Обработка осталась наблюдаемой и внутри платформы. Команда отслеживает загрузку CPU и памяти контейнеров и читает логи в режиме реального времени внутри той же платформы, а данные остаются там, где их можно отследить от начала до конца. Для компании, которая регулярно отвечает на подробные вопросы отделов рисков и комплаенса, сохранение такой прозрачности в одном месте так же важно, как и скорость.
Есть еще один плюс, и он имеет накопительный эффект. Теперь это повторяемый шаблон. Тот же Python UDF, который используется для фонетического ключа, может выполнять внутренние преобразования отчетности, которые до сих пор запускаются во внешних пакетных заданиях, или любую другую пользовательскую логику, которая не вписывается в SQL, но должна находиться рядом с данными.
Заключительные мысли
Для платформы с регулируемыми данными привлекательность Python UDF заключается не только в скорости или стоимости. Она в том, что вы перестаете идти на компромисс между хранением кода рядом с данными и использованием того языка, на котором вы действительно работаете, не теряя при этом возможности точно сказать, где обрабатываются ваши данные. DataVue получила одну реализацию, более низкие затраты и одновременно с этим более прозрачную историю соответствия требованиям. Вывод прост: при наличии правильных примитивов базы данных командам больше не нужно выбирать между хранением кода рядом с данными и написанием его на том языке, который они действительно используют.
Этот пост отражает продолжающееся сотрудничество между инженерными командами DataVue и SingleStore. Показатели производительности описывают рабочую нагрузку в производственной среде DataVue и будут продолжать проверяться по мере внедрения этого шаблона для других задач.










