Обновить
128K+

SQL *

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

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

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

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

В 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 мин
Охват и читатели4.3K

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

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

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

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

Читать далее

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

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

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

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

Читать далее

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

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

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

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

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

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

Читать далее

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

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

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

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

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

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

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

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

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

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

Читать далее

ETL + ELT = EtLT

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

Привет!

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

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

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

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

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

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

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

Читать далее

Аналитика Jira без API: считаем Lead Time, CFD и метрики релизов прямо в SQL по базе Postgres

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

У Jira есть REST API, есть JQL, есть маркетплейс с дашбордами. Но как только метрики становятся чуть сложнее, чем «сколько задач закрыто за спринт», всё это упирается в потолок:

Читать далее

Подключили LLM к базе на 253 таблицы тремя способами. Больше всех ошибались не модели

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

Мы в отделе поспорили, как подключать LLM к базе на 253 таблицы: MCP-инструменты или схема в промте. Собрали бенчмарк на 29 реальных вопросах аналитиков и померили три подхода по execution accuracy, деньгам и латентности. Победил вариант, за который не топил никто, а больше всех ошибался составитель бенчмарка: трижды, и один раз его поправила испытуемая модель. Внутри: таблицы с цифрами, четыре дефекта харнесса, которые выдавали правдоподобные числа вместо падений, и почему семантика, живущая в коде, — потолок любого подхода.

Читать далее

Из Oracle в PostgreSQL одним INSERT: DuckDB как ETL без Oracle-клиента

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

Когда говорят о DuckDB, обычно вспоминают аналитику: локальные запросы к Parquet, быстрые агрегации, ноутбуки. Но у него есть свойство, к аналитике отношения не имеющее: он умеет соединять источник и приёмник данных внутри одного SQL-плана. С расширениями для Oracle и PostgreSQL перенос данных сводится к одному запросу — без Instant Client, без OCI, без Python и без промежуточных файлов. А если одной сессии Oracle мало, чтение разбивается на параллельные шарды, читающие один согласованный снимок по единому SCN.

Читать далее

Интеграция Oracle с PostgreSQL через гетерогенный сервис

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

На Хабре не так много информации об интеграции между различными СУБД, и я решил поделиться своим опытом построения информационной системы на базе Oracle, которая взаимодействует с PostgreSQL (PG). Статья состоит их двух частей: в первой описана конфигурация СУБД, а во второй описан кейс по получению и обработке данных. Надеюсь, этот материал сэкономит Вам время при решении подобных задач.

Читать далее

Я добавил DuckDB в sqlize.online

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

Добавил DuckDB в sqlize.online и загрузил реальный датасет NYC Yellow Taxi — миллионы строк прямо в песочнице. Рассказываю, как всё работает, почему Parquet оказался удобным, и что даёт аналитический движок DuckDB в онлайн‑SQL песочнице.

Читать далее

Почему тип `numeric` в PostgreSQL такой медленный?

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

Три независимые попытки сделать для PostgreSQL быстрый точный десятичный тип расширением заглохли. Но не потому, что не получилось ускорить арифметику, — арифметику как раз каждое из них ускоряло. Тогда в чём же дело? Здесь я разбираю технические решения в устройстве numeric, которые приводят к высокой стоимости использования этого типа данных. Изучение провожу в сравнении с устройством типа decimal в DuckDB - будучи OLAP СУБД, он свободен от некоторых ограничений PostgreSQL, и гонясь за производительностью, выбирал другой путь развития.

Копнуть матчасть

Четыре антипаттерна CTE в PostgreSQL: разбираем на EXPLAIN ANALYZE

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

CTE в PostgreSQL упрощают код, но могут снижать производительность. Разбираем 4 антипаттерна, примеры EXPLAIN ANALYZE и практические способы оптимизации.

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

Common Table Expressions (CTE), или конструкции WITH, — привычный инструмент SQL-разработчика. Чем сложнее запрос, тем выше шанс встретить в нём WITH: код становится чище, а запутанная логика разбивается на понятные блоки. CTE используют как альтернативу вложенным запросам и временным таблицам. Однако за внешней простотой и читаемостью скрываются риски снижения производительности, которые не всегда удаётся предвидеть.

Такие запросы на первый взгляд выглядят правильными, но работают неэффективно, и проблема вылезает только в EXPLAIN ANALYZE (инструмент разбирали в прошлом гайде). Разберём четыре антипаттерна CTE, посмотрим планы выполнения и покажем, как переписать запрос. В конце — короткий чек-лист диагностики.

Эта статья может быть полезна начинающим разработчикам и аналитикам, которые уже полюбили синтаксис CTE, но хотят понять, что на самом деле происходит «под капотом» в PostgreSQL.

Читать далее

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

От struct к компиляции под схему: ускоряем RowBinary-декодер на Python

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

Я автор aiochlite — асинхронного клиента ClickHouse на aiohttp. Раньше мой декодер RowBinary читал каждое числовое поле отдельно. Если брать 200 тысяч строк с десятью числовыми колонками, получалось два миллиона таких чтений, хотя все данные уже были в памяти.

Сначала я думал использовать Cython, C или Rust. Но потом решил попробовать оптимизировать сам процесс: объединить соседние поля с фиксированной длиной в один struct, а полностью фиксированные строки разбирать с помощью Struct.iter_unpack. На числовых данных это ускорило работу примерно в 8.3 раза.

Со смешанной схемой данных получилось интереснее: простая склейка почти не помогла. Главной проблемой осталась проверка типов внутри основного цикла. В итоге я начал генерировать и компилировать Python-функцию под конкретную схему ответа — это дало ускорение еще примерно в 1.7 раза.

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

Читать далее

Исповедь бизнес-аналитика: о 25 отказах за день, первом тимлиде и любви к сложным задачам

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

Десять лет в таможне, второй пилот детсадовского возраста, привычная стабильность и… 25 отказов от IT-компаний в один день. Кажется, это идеальный рецепт для того, чтобы смириться и опустить руки. Но сегодня я — бизнес- и системный аналитик, кайфующий от задач, «которые никто даже трехметровой палкой трогать бы не захотел». Это моя честная история о том, как перебороть карьерную инерцию, превратить опыт госслужбы в хард-скиллы и найти ту самую команду, где тимлид перед дейликом «обнял, приподнял и покружил».

Читать далее

Оптимизация агрегатов PostgreSQL — что может расширение?

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

Агрегаты в PostgreSQL не очень-то эффективны. Это особенно заметно в сравнении с SQL Server в сценарии, где частичная агрегация не помогает: когда агрегация только подготавливает данные для запроса, обрабатывая большой поток строк и на выходе получая ненамного меньший набор групп и посчитанных по ним агрегатов. Хуже всего приходится типам переменной длины. И здесь характерный пример — SUM(numeric). Встроенные агрегаты обязаны обрабатывать значения в самом общем виде, тогда как на практике данные часто ограничены: например, в БД 1С все numeric имеют фиксированный масштаб.

Отсюда возникает идея оптимизировать агрегаты, подстроив их под конкретные условия эксплуатации. Раньше это было возможно только в форке PostgreSQL. Однако недавно David Rowley добавил в ядро любопытный инструмент расширения SupportRequestSimplifyAggref (коммит 42473b3b31, PostgreSQL 19): теперь можно предоставить планнеру кастомную логику трансформации агрегата через механизм функций поддержки планнера (prosupport). Сам механизм существует ещё с PostgreSQL 12, но до агрегатов добрался только сейчас. В ядре новый запрос применяется скромно: заменяет COUNT(1) и COUNT(col) по NOT NULL-колонке на COUNT(*). А вот расширению он позволяет сделать с агрегатом во время планирования практически что угодно. Это открывает пространство для интересных технических решений.

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

Читать далее

Отчет для отдела продаж в BI конструкторе Битрикс24

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

Привет, технари, я на Хабре недавно, решил делиться своей экспертизой и общаться с единомышленниками, чтобы иметь окружение схожих себе и обмениваться опытом. Сам своими руками сделал более 70 интеграций Битрикс24 и AmoCRM за 3 года, есть что выложить из опыта.

Отделам продаж постоянно нужны отчеты: конверсии, звонки и так далее, но особо развитым кампаниям надо отчеты уже кастомные, не шаблон. Если брать шаблонные отчеты в Битрикс24, то там кусок фронта достаточно шаблонный, что и обычно для CRM которая «для всех», это же не самописка. Там есть Конструктор отчетов, но там тоже очень много ограничений.

А если РОП или директор по продажам хочет кастомный отчет? В Rest API лезть?

При большом желании можно и в API лезть, но в Битрикс24 есть промежуточный вариант, полушаблон, полукод (кастом) — BI конструктор.

[В статье немеряно скриншотов — прим. НЛО]

Читать далее

Как уронить базу данных

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

Так получилось, что пару десятилетий занимался в тои числе и базами данных. Ставил. Тюнил. Выносил логику В базу. Вынос иллогику ИЗ базы. Поднимал когда падали... Когда перешёл в большой SRE‑спорт, почти октаду лет поддерживал экзабайтные аналитические query engine. В общем, развлекался, как мог.

Главное открытие заключалось в том, что почти всё, что считается невозможным, случается. Люди креативны. Ты им дашь регексп — и они начнут майнить биткойны. Ты им дашь data lake — и они начнут хранить данные в именах таблиц. Ты им дашь GEO... Сам виноват.

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

И это ещё хороший сценарий, так как никто ничего плохого и не хотел: можно поймать запрос, заблокировать, и спокойно разбираться.

Роняем

Пишем свой Native Filter плагин для Apache Superset: пошаговый рабочий туториал

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

Всем привет! Меня зовут Александр Цай, я ведущий инженер-аналитик в МТС Web Services.
Занимаюсь всем, что связано с данными и ИИ. Найти, заполучить, обработать, спроектировать, развернуть — это все ко мне.

Опущу все нудные подробности, решили мы развернуть себе Superset 6.1.0 — последнюю версию, но столкнулись с тем, что заказчику категорически не нравится штатный фильтр по датам и он не хочет пересаживаться со своего BI, а хочет он календарик. А еще — пару плагинов с оглядкой на PowerBI. Поэтому встал вопрос создания собственного плагина-фильтра.

Казалось бы, задача несложная. Пара-тройка гайдов в en сегменте имеется, есть даже документация и штатный генератор шаблонов. Но по факту оказалось, что все это не работает. Генератор так вообще не обновлялся аж с 2024 года: выдает шаблон, который ссылается на уже несуществующие классы и типы, что автоматически делает все гайды неактуальными…

А что все это значит? Время написать свой собственный!
Об этом и расскажу в сегодняшнем материале. 

Дисклеймер: Я питонист до мозга костей и в тайпскрипте, да и фронте в целом, понимаю не очень много. Простите меня, адепты сего языка программирования, но код самого плагина навайбкожен (хоть и проверен насколько я смог).
В npm не запушил тоже умышленно, цель статьи дать исходники и показать, как можно собрать плагин. Любой желающий может что-то додумать и доработать, собрать или разобрать и так далее.

Читать дальше

Почему в БД на PostgreSQL популярен тип numeric?

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

Документация PostgreSQL по numeric содержит два плохо согласующихся утверждения:

«especially recommended for storing monetary amounts and other quantities where exactness is required» — и сразу же: «calculations on numeric values are very slow compared to the integer types, or to the floating-point types». То есть рекомендуют для хранения денежных величин и тут же признают, что это весьма дорого.

Для меня, как разработчика СУБД это сигнал к действию. Если операции с типом заметно медленнее bigint, возникает соблазн: а нельзя ли хранить денежные величины целым числом копеек и округлять по стандартному правилу? Это бы прилично сэкономило вычислительные ресурсы наших серверов баз данных, разве нет? А что, если вообще использовать double precision?

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