Обновить
128K+

SQL *

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

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

FIFO на миллионах строк: как подружить бонусы, SQL и асимметричный N×M-граф

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

Всем привет! Меня зовут Иван Привалов, я разработчик в команде BI Авито Финтеха и в этой статье расскажу, как мы сделали FIFO-сопоставление между N начислений и M списаний для бонусов. Заодно покажу подвох, без которого SQL быстро превращался в тыкву.

Статья будет полезна аналитикам и data-инженерам уровней мидл+, которые работают с финансовыми данными в Trino, Presto и Spark SQL.

Читать далее

SQL JOIN Простыми Словами для Начинающих

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

JOIN - крайне популярная операция в SQL, о которой еще и спрашивают на 99% собеседований на программиста. Но когда начинаешь впервые разбираться с ней, то постоянно путаешься, какие таблицы соединять и когда именно.

В этой статье простыми словами и с великолепной графикой расскажу, что такое JOIN в SQL, что такое Foreign Key, какой тип JOIN когда использовать - INNER или OUTER - и зачем вообще.

Читать далее

Внедрение SQLMesh в команду аналитики

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

Каждая команда аналитики рано или поздно сталкивается с одной и той же проблемой: SQL-скрипты начинают жить своей жизнью, lineage оказывается неполным, ручные расчеты теряются в ноутбуках и Python-файлах, а любое изменение в базе данных превращается в потенциальную аварию. Мы долго искали инструмент, который позволил бы хранить данные как код, автоматически управлять зависимостями и при этом не требовал построения очередного сложного зоопарка из Airflow, dbt и десятка вспомогательных сервисов.

В этой статье я расскажу о нашем опыте внедрения SQLMesh поверх ClickHouse: как мы получили воспроизводимые расчеты, изолированные окружения для разработки, автоматический backfill, lineage для ручных отчетов через seeds и почему в некоторых сценариях SQLMesh оказался удобнее привычного dbt. Разберем реальные примеры моделей, окружений и практические кейсы, с которыми столкнулись в работе.

Читать далее

10 дней спустя: как мой бот дважды умирал незаметно, а метрика релевантности мне врала

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

Полторы недели назад я выложил на Habr бота с лентой хороших новостей на sqlite-vec за $5/мес. Потом пришли живые юзеры — и началось самое интересное. Не код. Эксплуатация.

За 10 дней в проде:

🪦 Бот дважды умирал незаметно — поллил Telegram и казался живым, но не создавал ни одной новости по 4–5 дней. Один раз — OOM на загрузке модели, другой — feedparser.parse(url) без таймаута заморозил весь пайплайн.

📉 Метрика релевантности «рухнула» до 30% — и я чуть не откатил рабочую фичу. Оказалось, один юзер поставил 106 дизлайков из 228 и отравил и метрику, и приор источников. Починил, считая по уникальным юзерам — правда оказалась 42%.

🎯 Реакции 78 человек сами показали, какие источники выкинуть: tech-аудитория отвергает общие новости и любит курируемое.

Внутри — реальные логи, код фиксов (httpx-таймаут, watchdog, робастные метрики) и уроки про надёжность воркеров и доверие к цифрам.

👉 @futur_e_news_bot

Читать далее

Когда мониторинг молчит: поиск скрытых деградаций сети с помощью ClickHouse

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

В телеком-сети возник класс «тихих» деградаций: абоненты сообщали, что при отличном уровне сигнала невозможно совершить или принять голосовой вызов, при этом вендорский мониторинг не фиксировал аварий. С точки зрения метрик оборудование оставалось «зеленым», а проблема обнаруживалась только по пользовательским жалобам.

Задача сводилась к автоматическому выявлению таких инцидентов на десятках тысяч объектов сети, используя только исторические временные ряды в ClickHouse, без вынесения вычислений во внешние системы.

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

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

Показана реализация на SQL в ClickHouse с применением паттерна Islands & Gaps для выделения инцидентов во временных рядах.

Разбор SQL-решения

Пишем автомигратор на Go: как узнать схему PostgreSQL

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

Когда говорят «генератор миграций», обычно в голове сразу появляется что-то вроде:

Генератор миграций начинается не с CREATE TABLE, а с вопроса: как представить текущую схему базы в коде?

В первой статье серии разбираем PostgreSQL-first introspector: читаем таблицы, колонки, constraints и индексы, где хватает information_schema, а где приходится идти в pg_catalog, и собираем детерминированный snapshot схемы. Миграции пока не генерируем — строим фундамент, из которого потом можно будет сделать diff и получить DDL.

Статья будет полезна тем, кто пишет инструменты вокруг баз данных, интересуется PostgreSQL internals или хочет понять, почему автомигратор — это не просто набор ALTER TABLE.

Читать далее

REDB: индексы, или почему на любую схему — это быстро

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

В предыдущей части цикла разобрали 13 таблиц REDB: как устроены objectsvaluesstructures, как RTTI-хранение значений отличается от старого EAV-паттерна, зачем нужен scheme_metadata_cache. Если не читали — начните с неё, без понимания схемы дальше тяжело.

В этой статье — то, что обычно идёт следующим вопросом: «А индексы где? У вас же значения всех полей лежат в одной таблице. Любой WHERE — это Seq Scan по миллионам строк».

Это статья 1.1, а не 2 — потому что она прямое продолжение разговора про физическое хранение. Глубокое погружение в C# — это статьи 3-5 цикла: Code-first схемы (SyncSchemeAsync<T>), CRUD (SaveAsync/LoadAsync), LINQ-транслятор. Здесь разговор остаётся в плоскости БД и DDL.

Цифры, на которые опираемся, — с реального прода: TSUM, логистическая система, обслуживает движение грузовиков и заказов через РЦ.

Читать далее

Всё о Supabase: установка, примеры, аналоги

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

Шесть лет назад, в начале 2020 года, группа разработчиков оглянулась на Firebase и подумала: «А давайте сделаем то же самое, но открытым кодом и на SQL!» Так родился Supabase: проект с искренней целью дать разработчикам контроль над данными и избавить от проприетарных заморочек.

А с распространением Vibe Coding, когда нейросети удобнее работать с API, а не писать логику для СУБД, взлёт Supabase пошел по экспоненте.

Читать далее

VARCHAR(N) в PostgreSQL: ограничение, а не экономия памяти

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

varchar(255) выглядит как аккуратное ограничение и часто воспринимается как способ сэкономить место.
Но в PostgreSQL это не так: база хранит фактическую строку, а не заранее выделяет память под весь лимит.

Разбираемся, что на самом деле делает VARCHAR(N), чем он отличается от text, когда ограничение полезно, а когда просто превращается в число, которое притворяется архитектурой.

Читать далее

2 + 2 = 6 и как мы это фиксим: lost updates в Postgres

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

Каждый бэкенд-разработчик, который хоть раз готовился к собеседованию, слышал про аббревиатуру ACID. Какая-то часть из слышавших сможет её расшифровать. Какая-то часть из расшифровавших — объяснить, почему важен каждый из принципов, скрытых за этими четырьмя буквами. И уж точно каждый из этих замечательных разработчиков знает цену букве «I» — isolation, изоляции транзакций.

Те, кого заинтересовал заголовок, скорее всего, относятся к одной из трех категорий читателей:

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

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

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

В этом материале систематизируем способы бороться с race conditions в Postgres и считаем, во сколько обходится каждый.

Читать далее

Почему мы выбрали рекурсивные SQL-запросы вместо GraphQL для графа знаний

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

Сравниваем нативный Property Graph в Spanner с рекурсивными CTE в AlloyDB — и объясняем, почему для персональной wiki второй подход оказался практичнее

Читать далее

nORM — ORM, но есть одно «no»

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

Если вы работаете с базами данных и используете ORM, вы, вероятно, сталкивались с той же проблемой, что и я. ORM отлично подходят для отображения таблиц на объекты. Но они начинают мешать, когда запрос становится сложным: агрегации, тщательно продуманные JOIN’ы, формы отчетов, которые не соответствуют одной модели на таблицу. Вы боретесь с ORM, переходите на сырой SQL, а затем вручную пишете связующий код (маппинг).

Не каждый SELECT возвращает то, что подходит под одну ORM-модель. SQL - это лучший язык для доступа к данным. Лучшие ORM, которые я использовал, такие как Drizzle, побеждают, потому что они остаются близки к SQL. Я хотел пойти дальше: хранить SQL в системе контроля версий и генерировать из него типизированный Python.

Именно поэтому я создал nORM (no ORM - не ORM) и выпустил версию v0.1.0 на этой неделе (мой первый опенсорс проект).

Читать далее

Как мы убрали очередь из REFRESH MATERIALIZED VIEW в PostgreSQL

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

У нас был долгий REFRESH MATERIALIZED VIEW: один запуск мог идти около часа, а повторные запуски вставали в очередь и держали соединения. CONCURRENTLY помогал не блокировать чтение из materialized view, но не решал проблему очереди одинаковых REFRESH.

Мы сделали механизм в PostgreSQL: триггерами отмечаем изменения в зависимых таблицах, храним зависимости каждой MV в служебной таблице, а перед обновлением берём pg_try_advisory_xact_lock по конкретной MV. Если lock не удалось взять — значит, обновление уже идёт, и второй REFRESH не ждёт в очереди, а пропускается.

Читать далее

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

Использование триггеров в БД для решения задач администрирования Sigla Vision

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

Продолжаем серию «Адаптивное администрирование Sigla Vision». Разберем кейсы, где триггеры в базе FineDB помогают решать задачи администрирования Sigla Vision.

Привет, Хабр! Меня зовут Всеволод Коваленко. В Газпромбанке я занимаюсь развитием функционала BI-системы на базе Sigla Vision.

В предыдущей статье «Версионирование таблиц репозитория метаданных Sigla Vision» мы разобрали исторические таблицы, которые хранят данные о состояниях записей в БД. Версионирование таблиц мы тоже строили на триггерах FineDB. Теперь покажем, как те же триггеры решают еще ряд задач администрирования Sigla Vision.

Читать далее

Функции управления цифровыми активами автомобильных дорог. Часть 2 – маппинг

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

Здравствуйте, уважаемые читатели Хабра!

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

Интересно? Читать!

Я люблю SQL, но устал собирать WHERE через fmt.Sprintf: зачем я сделал qrafter

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

Мне нравится чистый SQL.

Не «нравится, потому что пришлось», а правда нравится. В хорошем SQL‑запросе видно, что происходит с данными: откуда берём, как фильтруем, где соединяем, что агрегируем и в каком порядке отдаём наружу.

Но как только в API появляются фильтры, сортировка, пагинация и отдельный COUNT(*) с тем же WHERE, чистый SQL быстро обрастает ручной бухгалтерией: args, placeholder«ы, fmt.Sprintf и копирование условий между запросами.»

В какой‑то момент я понял, что меня раздражает не SQL. Меня раздражает работа вокруг SQL.

Так появился qrafter — небольшой type‑safe SQL query builder для Go: без ORM, без codegen, с типизированными колонками, зависимым от диалекта рендером и обычным SQL + аргументами на выходе.

Читать далее

Книга: «Изучаем SQL за месяц, занимаясь один час в день»

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

Привет, Хаброжители! SQL, «структурированный язык запросов» (Structured Query Language) — это универсальное средство создания, управления и составления запросов к реляционным базам данных, таким как SQL Server, PostgreSQL и Oracle. Для аналитиков данных SQL — суперинструмент, позволяющий выйти за пределы обычных табличных редакторов и систем бизнес-аналитики. При этом язык SQL интуитивен и на удивление прост: немного практики во время чтения книги — и вы уже с легкостью извлекаете данные, перестраиваете таблицы и создаете яркие, наглядные отчеты и презентации!

Читать далее

Как написать свое расширение postgres?

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

Привет, хабровчане! Сегодня покажу, как писать расширения для PostgreSQL. На примере pg_plan_alternatives, который логирует все пути, рассматриваемые планировщиком. Вы увидите то, что обычно скрывает планировщик.

Нам потребуется:

redb — типизированное хранилище для .NET поверх Postgres/MSSQL: без миграций, без Include, с полным LINQ

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

Типизированное хранилище для .NET поверх Postgres и MSSQL. C#-класс как схема — без миграций, без Include, с полным LINQ. Работает в проде.

LoadAsync вместо 40 Include →

Ваш PostgreSQL болеет молча. Десяток запросов, чтобы это увидеть

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

Пятница, вечер. Один эндпоинт начал отвечать восемь секунд вместо двухсот миллисекунд, а в Grafana всё зелёное. PostgreSQL редко падает громко — он неделями копит мёртвые строки, лишние индексы и зависшие транзакции, пока не станет совсем плохо.

В статье — пять SQL-запросов из моего queries.sql, которыми я реально пользуюсь: bloat и dead tuples, топ тяжёлых запросов по pg_stat_statements, неиспользуемые индексы, висящие транзакции и блокировки. Работают на голом PostgreSQL 13+

Читать далее