🦆 DuckDB + Python: мощный тандем для аналитики прямо на ноутбуке
Если вы работаете с аналитикой данных и вам важна скорость, гибкость и простота — попробуйте связку DuckDB + Python. Это встроенная колонко-ориентированная СУБД, которая отлично работает с pandas, Parquet и SQL-запросами — прямо в памяти, без сервера.
📌 Что такое DuckDB?
- Лёгкая SQL-база данных
- Работает как SQLite, но оптимизирована под аналитику
- Отлично справляется с файлами Parquet и Arrow
- Идеально для обработки больших наборов данных локально
🔗 Возможности интеграции с Python:
- Прямой запрос к pandas DataFrame:
- Работа с файлами:
- Использование SQL + pandas + визуализация в одном блоке
💡 Преимущества:
- 🚀 Быстрее pandas при агрегациях и фильтрации
- 🔗 Поддержка Parquet, CSV, JSON, Arrow и др.
- 🧠 SQL как первый язык аналитики — работает из коробки
- 🛠 Не требует отдельного сервера или установки СУБД
🧪 Это отличное решение для data science проектов, анализа больших логов, локальных ETL-задач и экспериментальной работы с данными.
🔍 Подробный гайд
#Python #DuckDB #DataAnalytics #Pandas #SQL #ETL
➡ SQL Community | Чат
Если вы работаете с аналитикой данных и вам важна скорость, гибкость и простота — попробуйте связку DuckDB + Python. Это встроенная колонко-ориентированная СУБД, которая отлично работает с pandas, Parquet и SQL-запросами — прямо в памяти, без сервера.
📌 Что такое DuckDB?
- Лёгкая SQL-база данных
- Работает как SQLite, но оптимизирована под аналитику
- Отлично справляется с файлами Parquet и Arrow
- Идеально для обработки больших наборов данных локально
🔗 Возможности интеграции с Python:
- Прямой запрос к pandas DataFrame:
con.execute("SELECT * FROM df WHERE col > 10").df()
- Работа с файлами:
con.execute("SELECT COUNT(*) FROM 'data.parquet'")
- Использование SQL + pandas + визуализация в одном блоке
💡 Преимущества:
- 🚀 Быстрее pandas при агрегациях и фильтрации
- 🔗 Поддержка Parquet, CSV, JSON, Arrow и др.
- 🧠 SQL как первый язык аналитики — работает из коробки
- 🛠 Не требует отдельного сервера или установки СУБД
🧪 Это отличное решение для data science проектов, анализа больших логов, локальных ETL-задач и экспериментальной работы с данными.
🔍 Подробный гайд
#Python #DuckDB #DataAnalytics #Pandas #SQL #ETL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤5👍4🥰1👏1
Forwarded from Python/ django
py-pglite — обёртка PGlite для Python, позволяющая запускать настоящую базу PostgreSQL прямо при тестах. Без Docker, без настройки — просто импортируй и работай.
📌 Почему это круто:
- 🧪 Ноль конфигурации: никакого Postgres и Docker, только Python
- ⚡ Молниеносный старт: 2–3 с против 30–60 с на традиционные подходы :contentReference[oaicite:2]{index=2}
- 🔐 Изолированные базы: новая база для каждого теста — чисто и безопасно
- 🏗️ Реальный Postgres: работает с JSONB, массивами, оконными функциями
- 🔌 Совместимость: SQLAlchemy, Django, psycopg, asyncpg — любая связка :contentReference[oaicite:3]{index=3}
💡 Примеры установки:
pip install py-pglite
pip install py-pglite[sqlalchemy] # SQLAlchemy/SQLModel
pip install py-pglite[django] # Django + pytest-django
pip install py-pglite[asyncpg] # Асинхронный клиент
pip install py-pglite[all] # Всё сразу
🔧 Пример (SQLAlchemy)
python
def test_sqlalchemy_just_works(pglite_session):
user = User(name="Alice")
pglite_session.add(user)
pglite_session.commit()
assert user.id is not None
py‑pglite — идеальный инструмент для unit- и интеграционных тестов, где нужен настоящий Postgres, но без всей админской рутины.
Полноценный PostgreSQL — без его тяжеловесности.
▪Github
@pythonl
#python #sql #PostgreSQL #opensource
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤4🥰3
This media is not supported in your browser
VIEW IN TELEGRAM
🗓️ SQL-трюк: как быстро найти "дыры" в данных по датам
В аналитике часто нужно понять, за какие дни нет записей — например, продаж или логов.
Вместо сложных процедур можно сгенерировать календарь через
https://www.youtube.com/shorts/CAkHyUx6iiU
#SQL #Postgres #DataAnalytics #generate_series
В аналитике часто нужно понять, за какие дни нет записей — например, продаж или логов.
Вместо сложных процедур можно сгенерировать календарь через
generate_series() (Postgres) и сделать LEFT JOIN к данным. Так вы мгновенно выявите пропуски и сможете строить непрерывные временные ряды.
-- Дни без заказов за последние 30 дней
WITH calendar AS (
SELECT generate_series(
current_date - interval '30 days',
current_date,
interval '1 day'
)::date AS day
),
orders_per_day AS (
SELECT
order_ts::date AS day,
COUNT(*) AS orders_count
FROM sales
WHERE order_ts >= current_date - interval '30 days'
GROUP BY order_ts::date
)
SELECT
c.day,
COALESCE(o.orders_count, 0) AS orders_count
FROM calendar c
LEFT JOIN orders_per_day o USING(day)
WHERE o.orders_count IS NULL
ORDER BY c.day;
https://www.youtube.com/shorts/CAkHyUx6iiU
#SQL #Postgres #DataAnalytics #generate_series
👍14❤8🔥4
sql-basics-cheat-sheet-a4.pdf
120.5 KB
#sql #doc #cheatsheet
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤1🔥1😁1
Продвинутый SQL-прием: partial index вместо “универсального” индекса
Если в таблице много строк, но запрос почти всегда смотрит только активные записи, не обязательно индексировать всё.
Например, есть таблица заказов:
Обычный индекс:
Работает, но он хранит данные по всем статусам: active, cancelled, archived, failed и так далее.
Если чаще всего нужны только активные заказы, можно сделать partial index:
Такой индекс меньше, быстрее обновляется и лучше помещается в память. Планировщик сможет использовать его для запросов, где условие совпадает:
Индекс не обязан покрывать всю таблицу. Иногда лучший индекс - это индекс только по тем строкам, которые реально участвуют в горячих запросах.
Особенно полезно для флагов вроде deleted_at IS NULL, status = 'active', is_published = true, processed = false.
#sql #postgresql #database #backend
Если в таблице много строк, но запрос почти всегда смотрит только активные записи, не обязательно индексировать всё.
Например, есть таблица заказов:
SELECT *
FROM orders
WHERE user_id = 42
AND status = 'active';
Обычный индекс:
CREATE INDEX idx_orders_user_status
ON orders(user_id, status);
Работает, но он хранит данные по всем статусам: active, cancelled, archived, failed и так далее.
Если чаще всего нужны только активные заказы, можно сделать partial index:
CREATE INDEX idx_orders_active_user
ON orders(user_id)
WHERE status = 'active';
Такой индекс меньше, быстрее обновляется и лучше помещается в память. Планировщик сможет использовать его для запросов, где условие совпадает:
SELECT *
FROM orders
WHERE user_id = 42
AND status = 'active';
Индекс не обязан покрывать всю таблицу. Иногда лучший индекс - это индекс только по тем строкам, которые реально участвуют в горячих запросах.
Особенно полезно для флагов вроде deleted_at IS NULL, status = 'active', is_published = true, processed = false.
#sql #postgresql #database #backend
❤6👍5🔥1😁1
Вопрос на SQL собеседовании.
Какой оператор имеет больший приоритет AND или OR (если они используются совместно)?
Ответ:
AND имеет больший приоритет, нежели OR
#sql #собеседование
Какой оператор имеет больший приоритет AND или OR (если они используются совместно)?
Ответ:
#sql #собеседование
3👍10❤1😁1
This media is not supported in your browser
VIEW IN TELEGRAM
Одна маленькая звёздочка в SQL может незаметно просадить весь backend.
На первый взгляд всё логично: зачем перечислять поля, если можно забрать из таблицы сразу всё? На тестах быстро, в разработке удобно, проблем не видно.
Но потом в таблицу добавляют тяжёлый JSON, аватар, длинный текст или служебные данные. И старый код внезапно начинает таскать лишние мегабайты на каждый запрос.
Дальше всё сыпется по цепочке: растёт трафик, запросы тормозят, память уходит быстрее, кэш работает хуже, а любое изменение схемы становится рискованнее.
Поэтому в продакшене лучше выбирать только те поля, которые реально нужны приложению.
Звёздочка удобна для быстрой проверки. Но в рабочем коде это та самая лень, которая потом больно бьёт по продакшену.
#sql #backend #database #postgresql #mysql #разработка #программирование #devtips #webdev
На первый взгляд всё логично: зачем перечислять поля, если можно забрать из таблицы сразу всё? На тестах быстро, в разработке удобно, проблем не видно.
Но потом в таблицу добавляют тяжёлый JSON, аватар, длинный текст или служебные данные. И старый код внезапно начинает таскать лишние мегабайты на каждый запрос.
Дальше всё сыпется по цепочке: растёт трафик, запросы тормозят, память уходит быстрее, кэш работает хуже, а любое изменение схемы становится рискованнее.
Поэтому в продакшене лучше выбирать только те поля, которые реально нужны приложению.
Звёздочка удобна для быстрой проверки. Но в рабочем коде это та самая лень, которая потом больно бьёт по продакшену.
#sql #backend #database #postgresql #mysql #разработка #программирование #devtips #webdev
👍7❤3🤔1
💡 SQL-трюк: сравнивайте `NULL` без костылей
В PostgreSQL обычное сравнение может неожиданно сломать условие:
Результат:
Потому что
Из-за этого часто пишут громоздкие условия:
Но есть оператор, о котором многие забывают:
Он работает как NULL-safe equality:
Есть и обратный вариант:
Например, удобно искать реально изменившиеся значения:
Если оба
Без этого обычное:
может просто вернуть
Особенно полезно при синхронизации данных, аудите изменений, ETL и UPSERT-логике.
#SQL #PostgreSQL #Database
В PostgreSQL обычное сравнение может неожиданно сломать условие:
SELECT NULL = NULL;
Результат:
NULL
Потому что
NULL означает «неизвестное значение», а не конкретное значение.Из-за этого часто пишут громоздкие условия:
WHERE a = b
OR (a IS NULL AND b IS NULL)
Но есть оператор, о котором многие забывают:
a IS NOT DISTINCT FROM b
Он работает как NULL-safe equality:
SELECT NULL IS NOT DISTINCT FROM NULL; -- true
SELECT 10 IS NOT DISTINCT FROM 10; -- true
SELECT 10 IS NOT DISTINCT FROM NULL; -- false
Есть и обратный вариант:
a IS DISTINCT FROM b
Например, удобно искать реально изменившиеся значения:
SELECT *
FROM old_data o
JOIN new_data n USING (id)
WHERE o.email IS DISTINCT FROM n.email;
Если оба
email = NULL, строка не считается изменённой.Без этого обычное:
o.email <> n.email
может просто вернуть
NULL и пропустить изменение.Особенно полезно при синхронизации данных, аудите изменений, ETL и UPSERT-логике.
#SQL #PostgreSQL #Database
❤10👍5🔥2
⚡️ QueryTuner - open-source инструмент, который разбирает SQL-запрос и показывает, почему он может тормозить.
Подключаться к базе вообще не обязательно. Можно просто вставить SQL и получить диагностику.
Поддерживаются сразу 5 диалектов:
- PostgreSQL
- MySQL
- Oracle
- SQL Server
- SQLite
Внутри два уровня анализа.
1. Детерминированный heuristic engine
Он мгновенно ищет типичные anti-patterns:
-
- функции внутри
- leading wildcard в
- потенциально отсутствующие индексы
-
- другие проблемы производительности
Сейчас заявлено 12 правил, и для них не нужны ни LLM, ни внешний API.
2. Опциональный AI-слой
Можно подключить Qwen через Hugging Face или OpenAI. Тогда QueryTuner умеет:
- объяснять проблему человеческим языком;
- переписывать запрос;
- предлагать
- объяснять, зачем конкретный индекс нужен.
Особенно интересно, что можно передать ещё и
Например, для такого запроса:
Хороший проект для тех случаев, когда SQL уже работает, но хочется понять, почему через полгода он начнёт работать плохо.
#SQL #PostgreSQL #Database #OpenSource #DataEngineering
https://github.com/AutoShiftOps/querytuner
Подключаться к базе вообще не обязательно. Можно просто вставить SQL и получить диагностику.
Поддерживаются сразу 5 диалектов:
- PostgreSQL
- MySQL
- Oracle
- SQL Server
- SQLite
Внутри два уровня анализа.
1. Детерминированный heuristic engine
Он мгновенно ищет типичные anti-patterns:
-
SELECT *- функции внутри
WHERE- leading wildcard в
LIKE- потенциально отсутствующие индексы
-
ORDER BY без ограничения результата- другие проблемы производительности
Сейчас заявлено 12 правил, и для них не нужны ни LLM, ни внешний API.
2. Опциональный AI-слой
Можно подключить Qwen через Hugging Face или OpenAI. Тогда QueryTuner умеет:
- объяснять проблему человеческим языком;
- переписывать запрос;
- предлагать
CREATE INDEX;- объяснять, зачем конкретный индекс нужен.
Особенно интересно, что можно передать ещё и
CREATE TABLE DDL. Тогда рекомендации становятся schema-aware: инструмент видит реальные таблицы, колонки и существующие индексы. Например, для такого запроса:
SELECT *
FROM orders
WHERE YEAR(created_at) = 2026;
Хороший проект для тех случаев, когда SQL уже работает, но хочется понять, почему через полгода он начнёт работать плохо.
#SQL #PostgreSQL #Database #OpenSource #DataEngineering
https://github.com/AutoShiftOps/querytuner
👍11🔥3❤2💊1
Media is too big
VIEW IN TELEGRAM
SQL: Один NULL в списке, и NOT IN возвращает ноль строк
WHERE id NOT IN (1, 2, NULL) раскрывается в id <> 1 AND id <> 2 AND id <> NULL. Последнее сравнение всегда даёт UNKNOWN, а WHERE пропускает только TRUE, поэтому запрос молча возвращает пустой результат. Одно неизвестное значение отравляет весь фильтр. Если в подзапросе возможен NULL, бери NOT EXISTS: он на NULL не ломается и читается понятнее, чем костыль с IS NOT NULL.
#sql #deathnote
WHERE id NOT IN (1, 2, NULL) раскрывается в id <> 1 AND id <> 2 AND id <> NULL. Последнее сравнение всегда даёт UNKNOWN, а WHERE пропускает только TRUE, поэтому запрос молча возвращает пустой результат. Одно неизвестное значение отравляет весь фильтр. Если в подзапросе возможен NULL, бери NOT EXISTS: он на NULL не ломается и читается понятнее, чем костыль с IS NOT NULL.
#sql #deathnote
👍9❤2🔥1
⚡️ SQL-задача с подвохом
Что вернёт этот запрос в PostgreSQL?
Многие ожидают:
Но результат будет другим:
1 | 100 | 200
2 | 100 | 200
3 | 200 | 400
По умолчанию PostgreSQL использует окно. Строки с одинаковым считаются равными соседями и попадают в окно вместе.
Для построчного накопления нужно указать :
SUM(amount) OVER (
ORDER BY amount, id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)
#SQL #PostgreSQL #Database
Что вернёт этот запрос в PostgreSQL?
CREATE TABLE payments (
id int,
amount int
);
INSERT INTO payments VALUES
(1, 100),
(2, 100),
(3, 200);
SELECT
id,
amount,
SUM(amount) OVER (ORDER BY amount) AS total
FROM payments
ORDER BY id;
Многие ожидают:
1 | 100 | 100
2 | 100 | 200
3 | 200 | 400
Но результат будет другим:
1 | 100 | 200
2 | 100 | 200
3 | 200 | 400
По умолчанию PostgreSQL использует окно
RANGE ... CURRENT ROWamountДля построчного накопления нужно указать
ROWSSUM(amount) OVER (
ORDER BY amount, id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)
👍6🔥2