Обновить
64K+

SQL *

Формальный непроцедурный язык программирования

101,05
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

1.5 миллиона событий в день и ни одной таблицы events: как мы считали продуктовую аналитику 300K-бота по голому проду

Уровень сложностиСложный
Время на прочтение16 мин
Охват и читатели4.1K

Маркетолог прислал мне скрин дашборда и одно слово: «пусто».

На скрине — панель «Количество пришедших по реферальной ссылке за период». Ноль. Под ней — график регистраций. Тоже ноль. Ссылка, по которой он пришёл, вела на дашборд с фильтром по конкретному slug — тому самому, который он неделю крутил в закупке.

Я открыл ту же ссылку, поменял в урле from=now-6h на from=now-30d и увидел 16 регистраций.

Дефолтный интервал в Grafana — 6 часов. У бота ночью в этой гео никого нет. Аналитика работала идеально и показывала абсолютно честный ноль.

Это самая безобидная из историй, которые тут будут. Дальше — про то, как мы строили продуктовую аналитику для Telegram-бота с AI-персонажами на ~300K MAU, ~75 RPS в пике и ~1.5M событий в день: без ClickHouse, без Amplitude, без единой event-таблицы. Двенадцать дашбордов в Grafana поверх боевой MySQL. Три из них какое-то время врали, и это выяснилось не сразу.

Главный парадокс всего проекта помещается в одну строку: через систему проходит полтора миллиона событий в день, и ни одно из них не записано как событие. Есть только строки в продуктовых таблицах и их created_at. Всё, что вы прочитаете ниже, — следствие этого факта.

Статья — не туториал «подключите MySQL к Grafana за 10 шагов». Это разбор того, что происходит, когда продуктовые метрики приходится доставать из схемы, которую проектировали под продукт, а не под аналитику, — и когда по этим метрикам прямо сейчас решают, лить трафик дальше или нет.

Дисклеймер: проект под NDA, поэтому названия, точные объёмы и часть деталей изменены. Порядок величин, схема и сами проблемы — настоящие.

Читать далее

Новости

Как автоматизировать выгрузку данных из 1С: SQL или готовый ETL-инструмент

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели4.1K

Как организовать регулярную выгрузку данных из 1С, если ручной экспорт уже не справляется с объемом и частотой обновлений? В статье сравниваются два подхода: прямой доступ к базе через SQL и использование готового ETL-инструмента. Разбираем скорость, сложность настройки, требования к специалистам, риски для безопасности и сопровождения системы. Также показываем, в каких случаях оправдан SQL, а когда удобнее использовать готовый инструмент для автоматической выгрузки данных по расписанию без постоянного участия разработчика.

Читать далее

Почему база не видит ваш предагрегат

Уровень сложностиСредний
Время на прочтение12 мин
Охват и читатели7.6K

Инженеры данных построили агрегат — маленькую таблицу «продажи по магазинам по дням». Отчёт из неё собирается за доли секунды. А сводная в Excel всё равно ждёт двадцать секунд и читает миллиард строк.

Разбираемся на живом ClickHouse, почему база не видит предагрегат, который для неё построили, какая форма запроса это лечит (одна и та же для ClickHouse, Snowflake и BigQuery) и почему в итоге вопрос не к базе, а к семантическому слою. Внутри — замер на миллиарде строк: 3 секунды против 37 миллисекунд, сравнение восьми баз и одно правило, которое стоит проверить в своём BI.

Читать далее

Как искать длинные хеши и ID с dict='keywords_32k'

Время на прочтение7 мин
Охват и читатели5.6K

Практическое руководство по поиску длинных хешей, event ID, message ID и email в Manticore Search: лимиты, точное сравнение, wildcard-поиск, токенизация, миграция и ограничения.

Читать далее

Задача в проекте оказалась обработана за 11 секунд до создания…

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели8.4K

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

Поэтому я сел за доработку согласно предыдущему плану, что я писал в той статье. Я решил идти по первому пути и сделать логирование асинхронным. Дело в том, что так это становится изолированной переменной, ведь банально легче доработать и тестировать, чем заниматься рефакторингом всего кода и разносить его по разным процессам. После доработки я конечно же решил протестировать новую версию и я очень удивился результатам. Изначально throughput действительно вырос, что обрадовало меня.

Я уже думал писать статью, но решил мимолетом запустить 175 воркеров. Это решение создало неожиданную проблему - задача оказалась обработана за 11 секунд до ее создания.

Читать далее

Локальная LLM миграция Vertica2Trino. Как довести до рабочего состояния, если модель не тянет

Уровень сложностиСредний
Время на прочтение11 мин
Охват и читатели9K

Привет, на связи команда BI-разработчиков коммерческого департамента: Алексей Дубинец и Павел Беспалов

В статье расскажем, как построили пайплайн миграции наших витрин с помощью локальной LLM. 

Сразу оговорюсь: это не история про то, как мы дали в Codex или Claude Code, написали скилл и получили магический результат. Покажем инженерную часть задачи: где локальная модель срабатывает не так, какие наивные решения не работают и что пришлось построить вокруг неё, чтобы перевод стал воспроизводимым.

Читать далее

ora2pg молча выбросил процедуру целиком, и это не самое обидное

Уровень сложностиСредний
Время на прочтение11 мин
Охват и читатели6.5K

ora2pg переносит схему с Oracle на PostgreSQL, и в целом переносит хорошо. Интересное начинается там, где он чего-то не осилил: он не падает и не ругается, а молча делает не то.

Процедура с AUTHID исчезает из вывода целиком, без ошибки и без строки в логе. TO_DATE с форматом RR молча возвращает 1 год до нашей эры. LONG RAW превращается в text, хотя сам ora2pg документирует bytea. Обработчик исключений после конвертации ловит SQLSTATE, которого PostgreSQL не возбуждает никогда.

Двадцать таких мест, все проверены на реальном ora2pg 25.0 и живом PostgreSQL 16, по каждому написано чем чинить.

Читать далее

Переход к неанонимным изменениям схемы СУРБД Firebird. Финальная часть: как факты становятся историей

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели7.8K

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

Читать далее

Как я собрал анализатор прочтений для Author.Today: Selenium → MS SQL → воронка

Время на прочтение11 мин
Охват и читатели7.7K

1. Зачем это нужно

Моя боль как автора (а я не только программист и к. т. н, но еще и писатель в жанре фантастики) – это отсутствие на сайте автор.тудей полноценного анализа статистики. Вся статистика ограничивается просмотрами, временем и средним временем прочтений по дням и главам, в виде шахматки:

Читать далее

Тестовое задание на аналитика DWH: 4 задачи с разбором

Уровень сложностиСложный
Время на прочтение21 мин
Охват и читатели12K

В статье разбираем реальное тестовое задание на позицию аналитика DWH: четыре коротких SQL-запроса. Все синтаксически корректны, все дают верный результат на контрольных данных. И в каждом спрятана предпосылка, при нарушении которой цифры в витрине становятся неверными — без ошибок, без предупреждений, просто другие числа в отчёте

Найти ошибки

Индекс как алфавитный указатель: как база ищет и почему иногда не находит

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели9.9K

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

Статья для тех, кто индексы ставил, но EXPLAIN читал по диагонали.

Читать далее

Как я собрала Customer 360 с нуля и что поняла про analytics engineering

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели5.8K

У банков и ритейлеров, с которыми я работала, почти всегда одна и та же боль: данные о клиенте размазаны по CRM, core-banking и платёжным системам, и никто не может ответить на простой вопрос — а что мы вообще знаем об этом клиенте прямо сейчас. Чтобы попрактиковаться в решении этой задачи и показать подход публично, я собрала pet-проект: end-to-end пайплайн, который строит единую витрину Customer 360 из синтетических данных.

Сразу оговорюсь: все данные генерируются локально скриптом и полностью синтетические. Кода или данных работодателя в проекте нет — это самостоятельная реализация архитектуры, которую я использую в повседневной работе DWH/data-аналитика.

Читать далее

Переход к неанонимным изменениям схемы СУРБД Firebird. Часть 2: журнал фактов

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели4.6K

В первой части был инструмент, который снимает схему Firebird и раскладывает её деревом файлов: один объект — один файл. Он отлично отвечает на вопрос «как эта процедура выглядит сейчас» и совершенно беспомощен в вопросе «кто её поменял в среду вечером». Дамп — это фотография, а нам нужен ещё и вахтенный журнал.

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

Читать далее

Ближайшие события

Переход к неанонимным изменениям схемы СУРБД Firebird. Часть 1: извлечение схемы

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели7.1K

Когда я только пришел на должность помощника DBA, я заметил, что все production базы фиксируют изменения странным образом, а именно каждый день в 00:00 вызывался скрипт, который выгружает схему БД Firebird, в виде файла script.sql, созданный встроенной утилитой isql. Далее делил весь файл на объекты (файлы), по группам (директориям) принадлежности, объясняю: есть кусок скрипта создания таблицы, он помещается в директорию 01_TABLES в виде отдельного файла названного в честь названия объекта который он содержит, и так далее. Чем же это плохо? А суть в том что разработчиков много, правки анонимны, история тяжело воспроизводимая. В такой каше сразу не разберешься.

Читать далее

Как я написал свой мигратор для ClickHouse — и почему он до сих пор жив

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели9.6K

В 2020-м мне понадобилось версионировать схему ClickHouse в CI/CD, а готового инструмента под Go с поддержкой ClickHouse не нашлось ни одного. Пришлось написать свой — db-migrator. Со временем он оброс поддержкой Postgres, MySQL, а недавно и Iceberg, и разошёлся среди коллег по отрасли. В статье расскажу, чем миграции в ClickHouse отличаются от привычного Postgres/MySQL и какие инженерные развилки из-за этого пришлось пройти: ON CLUSTER для обычного реплицированного кластера, режим Replicated-базы, аккуратная таблица истории миграций на шардированном кластере и маскирование секретов в логах.

Инструмент: https://github.com/raoptimus/db-migrator.go

Читать далее

redb 3.7.1: поиск по props быстрее до 100 раз. Альтернатива EF Core или дополнение к нему

Уровень сложностиСложный
Время на прочтение7 мин
Охват и читатели11K

Цена запроса не зависела от того, что ищешь: фильтр стоял над GROUP BY. Теперь отсечение идёт до агрегата, на трёх движках, без единой правки в коде приложения. До 100 раз на диапазоне по дате и в 5,3 раза на полной выборке в MS SQL Server.

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

Причина оказалась в форме сгенерированного SQL. Значения props живут построчно, и запрос сначала сворачивает их в широкую строку через GROUP BY, а уже потом применяет фильтр. Условие стояло над агрегатом, то есть фильтровало результат свёртки, а не колонку. Индексу там зацепиться не за что: к моменту проверки движок уже прочитал и свернул все значения всех объектов схемы. Триграммный индекс по строкам лежал без дела.

В 3.7.1 появился шаг, который ...

Читать далее

Как я искал скрытые паттерны в псевдо‑случайной генерации паролей пользователями

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели7.3K

И так, что мы имеем и для чего же собственно эта статья? Когда человеку ставят задачу в духе «Придумай пароль» — он берет и генерирует самостоятельно некую псевдослучайную последовательность, что в будущем именуется паролем (или с помощью генераторов паролей, которые встроены во все популярные браузеры, или с помощью установленных утилит). Казалось бы, можно и так понять, что самые часто используемые слова в духе «мама», «папа», «пароль» и другие — вполне объяснимы. Это то, что нас в большинстве своем объединяет, а потому может намного чаще встречаться в паролях. Не все люди хотят заморачиваться и отказываться от простых и понятных аналогиях. На примере старшего поколения моей семьи (бабуле) могу хоть сколько раз подтвердить, что ее излюбленный пароль был именем дочери и годом ее рождения.

А ведь в таких псевдо случайных генерациях можно встретить «проблему раскладки» (то, что проанализировано было в русском сегменте только в 2025 году следующими лицами: Леа Мюллер, Аушриус Юозапавичюс, Владимир Охримчук, Стефан Зюттерлин в работе «Поиск в словаре с использованием преобразованных русских слов на клавиатуре QWERTY», P. S. я мог допустить ошибки в переводе информации, за что прошу прощения). Если кратко, то это создает некую «маску», зная которую можно облегчить взлом. Подобные словари встречаются в открытом доступе, и еще чаще встречаются в недоброжелательном сообществе за разные суммы денег.

Читать далее

Oracle → PostgreSQL без даунтайма: как мы перевозили терабайт банковской базы и где всё ломалось

Уровень сложностиСложный
Время на прочтение11 мин
Охват и читатели8.3K

Задача звучала как задача из учебника: перенести кредитный домен банка с Oracle на PostgreSQL. 70+ таблиц, чуть больше терабайта данных, 500–3000 RPS на чтение и 50–300 на запись в пике. Одно ограничение: система обслуживает клиентов и не может остановиться. Ни на ночь, ни на выходные, ни «на 15 минут на переключение».

Эта статья — не туториал «как мигрировать за 10 шагов». Таких на Хабре десятки, и половина из них сводится к «запустите ora2pg». Здесь — список мест, где у нас всё ломалось, в порядке от «это все знают, но всё равно наступают» до «об этом мы узнали за неделю до переключения».

Если вы планируете такую миграцию, читайте как чеклист. Если уже прошли — сверьте, сколько совпало.

Дисклеймер: проект под NDA, поэтому названия, точные объёмы и часть деталей изменены. Порядок величин и сами проблемы — настоящие.

Читать далее

OAuth 2.0 в amoCRM REST API на PHP простым языком: получение, хранение и обновление токенов

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели5.5K

Когда впервые пишешь собственную интеграцию с amoCRM через REST API, сами запросы к сделкам, контактам или компаниям обычно оказываются не самой сложной частью.

Основной вопрос возникает раньше:

как один раз авторизовать интеграцию, а затем поддерживать доступ к amoCRM без постоянного ручного получения ключей?

1-2 года назад я реализовывал такую интеграцию на PHP. Токены хранили в MySQL, а работу с OAuth разбили на несколько отдельных файлов.

Сейчас решил восстановить общую архитектуру этой реализации.

Если убрать детали, OAuth-интеграция выглядит довольно просто:

Authorization Code → Access Token + Refresh Token → сохранение в БД → запросы к REST API → обновление токенов → повторное сохранение в БД.

Код авторизации берется в AmoCRM:

Читать далее

ETL + ELT = EtLT

Уровень сложностиПростой
Время на прочтение2 мин
Охват и читатели6.3K

Привет!

Заметка о правильности названий ETL процессов. Расставим точки над i.

Всегда было же нормально, коротко и звучно ETL. Теперь все чаще мелькает ELT, ETLT, EtLT.

Традиционный паттерн ETL, применяет бизнес-логику во время преобразования, до загрузки в хранилище. Выбрал данные, преобразовал, положил в хранилище. ELT меняет эту последовательность, сначала загружая сырые данные в хранилище, а преобразование выполняет уже внутри. ELT подход сокращает нагрузку на систему источник, позволяет итеративно совершенствовать логику преобразования. Имеем два противоположных метода.

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

Например, в потоке выполняется экстракция из базы данных, непосредственно при выборке происходят предварительные преобразования (отсечение миллисекунд у столбца времени), далее загрузка в цель - выполнился процесс ETL. Вторым этапом идут бизнес преобразования - процесс T, а вместе ETLT.

Таким образом и получается, что в большинстве случаев используется процесс ETLT, но исторически так сложилось называть все подобные процесcы просто и звучно ETL.
В аббревиатуре первая трансформация обозначается маленькой первой буквой t, и это не случайно. На данном шаге выполняются только предварительные преобразования данных: очистка, приведение типов. А вот уже вторая - это полноценная трансформация: бизнес преобразования, обогащения, расчеты и тд. Еще я встречал проставление индексов к буквам трансформаций ET1LT2.

Так же есть такое понятие как ETL++, но об этом в другой раз :-)

Читать далее
1
23 ...