7786
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it
👨💻 SQL PostgreSQL Patterns Library — большая коллекция готовых SQL-решений для PostgreSQL!
Здесь собраны практические запросы для работы со строками, JSON и массивами, поиска и оптимизации, массового обновления данных, индексов, миграций и администрирования БД. Есть решения для реальных задач: от UPSERT и поиска дубликатов до EXPLAIN, работы с миллионами записей, мониторинга запросов и обслуживания PostgreSQL.
Оставляю ссылочку: GitHub 📱
Как атомарно резервировать лимит без SELECT FOR UPDATE!
При работе с квотами, остатками и лимитами важно не допустить, чтобы конкурентные запросы одновременно прошли проверку одного и того же доступного значения. Если проверка выполняется отдельно от изменения данных, между этими операциями появляется окно гонки:
SELECT used, quota
FROM accounts
WHERE id = 42;
used = 80 при quota = 100 и каждый собирается зарезервировать ещё 15, обе проверки в приложении могут успешно пройти. UPDATE accounts
SET used = used + 15
WHERE id = 42
AND used + 15 <= quota
RETURNING used;
UPDATE одной строки сериализуется через row-level locking. Если другая транзакция успела изменить строку, условие WHERE для ожидавшего UPDATE будет повторно проверено относительно актуальной версии строки в READ COMMITTED:UPDATE accounts
SET used = used + :amount
WHERE id = :account_id
AND used <= quota - :amount
RETURNING id, used, quota;
RETURNING, резервирование выполнено. Если результат пустой, строка отсутствует либо доступного лимита недостаточно. Для прикладной логики эти случаи при необходимости можно различить отдельной проверкой после неуспешной попытки.amount >= 0: это стоит валидировать в приложении или закрепить ограничением на уровне БД:UPDATE inventory
SET reserved = reserved + :qty
WHERE product_id = :product_id
AND reserved <= stock - :qty
RETURNING product_id, reserved;
SELECT FOR UPDATE здесь нужен не всегда: если проверку можно выразить непосредственно в WHERE, сам UPDATE становится точкой синхронизации:UPDATE limits
SET consumed = consumed + :delta
WHERE id = :id
AND consumed <= maximum - :delta
RETURNING consumed;
consumed + delta <= maximum над одной строкой лучше проверять внутри атомарного UPDATE, а не между SELECT и UPDATE в приложении. Это сокращает критическую секцию и корректно работает при конкурентном изменении строки.
Разворачивайте несколько массивов вместе!
Когда приложение передаёт несколько связанных массивов, не нужно отдельно делать unnest(), нумеровать элементы и потом соединять их по позиции.
SELECT *
FROM unnest(
ARRAY[101, 102, 103],
ARRAY['book', 'mouse', 'keyboard'],
ARRAY[2, 1, 4]
) AS x(id, name, qty);
101/book/2, 102/mouse/1, 103/keyboard/4.INSERT INTO order_items (product_id, quantity)
SELECT *
FROM unnest(
:product_ids::bigint[],
:quantities::integer[]
);
UPDATE products p
SET price = x.price
FROM unnest(
:ids::bigint[],
:prices::numeric[]
) AS x(id, price)
WHERE p.id = x.id;
unnest(array1, array2, ...) объединяет связанные массивы в строки и позволяет массово добавлять или обновлять данные одним запросом.
Почему порядок колонок в составном индексе важен!
Составной индекс часто создают, когда запрос фильтрует данные сразу по нескольким колонкам. Но просто добавить нужные поля в индекс недостаточно — их порядок влияет на то, какую часть индекса PostgreSQL сможет эффективно использовать.
Есть таблица:
CREATE TABLE orders (
id BIGINT,
user_id BIGINT,
status VARCHAR(20),
created_at TIMESTAMPTZ,
amount NUMERIC(12,2)
);
SELECT
id,
created_at,
amount
FROM orders
WHERE user_id = 1500
AND created_at >= TIMESTAMPTZ '2026-09-01 00:00:00+00'
ORDER BY created_at;
CREATE INDEX idx_orders_user_created
ON orders (user_id, created_at);
user_id:user_id = 1500
created_at задаёт диапазон уже внутри записей этого пользователя:created_at >= TIMESTAMPTZ '2026-09-01 00:00:00+00'
ORDER BY created_at: при фиксированном user_id PostgreSQL может получить строки из индекса уже в нужном порядке и при подходящем плане обойтись без отдельной сортировки.CREATE INDEX idx_orders_created_user
ON orders (created_at, user_id);
created_at >= TIMESTAMPTZ '2026-09-01 00:00:00+00'
user_id всё ещё может участвовать в индексном сканировании, но уже не сокращает начальный диапазон B-tree так же эффективно, как в варианте (user_id, created_at). Разница особенно заметна, если за выбранный период накопились миллионы заказов разных пользователей.(user_id, created_at) хорошо подходит и для запроса только по ведущей колонке:WHERE user_id = 1500;
WHERE user_id = 1500
AND created_at >= TIMESTAMPTZ '2026-09-01 00:00:00+00';
created_at обычно не получает от этого индекса того же преимущества, поскольку условие на ведущую колонку отсутствует:WHERE created_at >= TIMESTAMPTZ '2026-09-01 00:00:00+00';
EXPLAIN (ANALYZE, BUFFERS)
SELECT
id,
created_at,
amount
FROM orders
WHERE user_id = 1500
AND created_at >= TIMESTAMPTZ '2026-09-01 00:00:00+00'
ORDER BY created_at;
ANALYZE orders;). На маленькой или пустой таблице PostgreSQL вполне может выбрать Seq Scan, и это будет нормальным поведением оптимизатора.(a, b) особенно эффективен сценарий, когда сначала ограничивается ведущая колонка a, а затем используется диапазон по b. Если запрос содержит равенство и диапазон, колонку с равенством часто имеет смысл поставить перед колонкой с диапазоном. Но окончательный выбор индекса должен подтверждаться реальным execution plan.
Составные индексы: правила проектирования и типичные ошибки!
Составные индексы используются для ускорения запросов по нескольким колонкам, но порядок полей внутри индекса напрямую влияет на его эффективность.
Представим таблицу заказов, где часто выполняются запросы по пользователю и дате создания заказа.
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
status VARCHAR(30),
created_at TIMESTAMP NOT NULL,
amount NUMERIC(10,2)
);
CREATE INDEX idx_orders_user
ON orders(user_id);
CREATE INDEX idx_orders_created_at
ON orders(created_at);
CREATE INDEX idx_orders_user_created_at
ON orders(user_id, created_at);
SELECT *
FROM orders
WHERE user_id = 42
AND created_at >= '2026-01-01';
user_id, а внутри одинаковых значений user_id — по created_at.SELECT *
FROM orders
WHERE user_id = 42;
SELECT *
FROM orders
WHERE created_at >= '2026-01-01';
CREATE INDEX idx_orders_created_at
ON orders(created_at);
CREATE INDEX idx_orders_all_columns
ON orders(user_id, status, created_at, amount);
EXPLAIN ANALYZE
SELECT *
FROM orders
WHERE user_id = 42
AND status = 'paid'
ORDER BY created_at DESC;
CREATE INDEX idx_orders_user_status_created_at
ON orders(user_id, status, created_at DESC);
😍 PostgreSQL Zero to Hero — большой русскоязычный материал по изучению PostgreSQL!
Здесь разобраны основы SQL, проектирование баз данных, индексы, транзакции, MVCC, WAL, оптимизация запросов, репликация, бэкапы и многое другое. Подойдёт разработчикам, которые хотят системно изучить PostgreSQL и разобраться не только с SQL, но и с архитектурой, производительностью, эксплуатацией базы данных.
Оставляю ссылочку: GitHub 📱
❤️ SQL-шпаргалка — основные конструкции и приёмы работы с базами данных!
Справочник по SQL с примерами запросов и пояснениями. Здесь на небольших таблицах разобраны INNER, LEFT, RIGHT, FULL и CROSS JOIN, а также показаны различия синтаксиса между PostgreSQL, MySQL, SQLite и SQL Server. Для команд указано, что именно они делают и в каких ситуациях применяются.
📌 Оставляю ссылочку: tools.sitebyme.ru
➡️ SQL Ready | #ресурс
🖥 PostgreSQL — управление последовательностями!Шпаргалка по работе с последовательностями в PostgreSQL: создание и удаление sequence, получение новых и текущих значений, сброс и синхронизация счётчика после импорта, а также привязка последовательности к столбцу. Помогает управлять генерацией идентификаторов и корректно работать со счётчиками при конкурентных вставках и загрузке данных.
➡️ SQL Ready | #шпора
Настройки только для одного запроса!
Необязательно менять statement_timeout, work_mem или другие параметры для всей сессии. SET LOCAL действует только до конца текущей транзакции.
BEGIN;
SET LOCAL lock_timeout = '500ms';
ALTER TABLE orders
ADD COLUMN source text;
COMMIT;
BEGIN;
SET LOCAL work_mem = '512MB';
SELECT customer_id, count(*)
FROM events
GROUP BY customer_id;
COMMIT;
work_mem для остальных запросов соединения.SET LOCAL позволяет тюнить PostgreSQL под конкретную операцию и автоматически возвращает настройки назад после COMMIT или ROLLBACK.
Почему OFFSET деградирует на больших таблицах!OFFSET часто используют для пагинации, потому что запрос выглядит просто. На небольших таблицах проблем обычно нет, но на больших объёмах стоимость такого подхода растёт вместе с глубиной страницы.
Есть таблица:
events(
id BIGINT,
user_id BIGINT,
payload JSONB,
created_at TIMESTAMPTZ
)
SELECT
id,
user_id,
created_at
FROM events
ORDER BY created_at DESC
LIMIT 50 OFFSET 1000000;
OFFSET. Ему нужно обработать строки до нужной позиции, а потом отбросить их.OFFSET + LIMIT записей, выбрасывает ненужные строки и возвращает только нужный результат.CREATE INDEX idx_events_created_at
ON events(created_at DESC);
OFFSET.LIMIT 50 OFFSET 1000000;
SELECT
id,
user_id,
created_at
FROM events
WHERE created_at < '2026-08-01 12:00:00'
ORDER BY created_at DESC
LIMIT 50;
created_at недостаточно, если несколько событий имеют одинаковое время.2026-08-01 12:00:00
2026-08-01 12:00:00
2026-08-01 12:00:00
CREATE INDEX idx_events_cursor
ON events(created_at DESC, id DESC);
SELECT
id,
user_id,
created_at
FROM events
WHERE (created_at, id) < ('2026-08-01 12:00:00', 1500000)
ORDER BY created_at DESC, id DESC
LIMIT 50;
LIMIT 50;
WHERE (created_at, id) < (...)
LIMIT 50;
OFFSET остаётся нормальным решением для административных интерфейсов, внутренних инструментов и небольших таблиц. Но для лент событий, истории операций, логов и больших списков он быстро становится узким местом.OFFSET удобен для разработки, но плохо масштабируется на больших объёмах данных. Для больших таблиц лучше использовать keyset pagination с составным индексом и стабильным курсором.
😍 zasqlpython — платформа для изучения и практики SQL!
Сайт позволяет изучать SQL с нуля и сразу закреплять материал на практике. Бесплатный курс включает 10 уроков и 92 задачи с автоматической проверкой прямо в браузере. После базового курса можно перейти к SQL-тренажёру с сотнями задач повышенной сложности и заданиями в формате собеседований.
📌 Оставляю ссылочку: zasqlpython.ru
➡️ SQL Ready | #ресурс
Почему ctid нельзя использовать как постоянный идентификатор!
В PostgreSQL каждая строка имеет системную колонку ctid. Она содержит физический адрес текущей версии строки в таблице: номер страницы и позицию строки внутри этой страницы.
Иногда ctid используют для поиска, удаления или диагностики отдельных записей, но важно понимать, что это не постоянный идентификатор строки. Значение ctid может измениться в процессе обычной работы базы данных, поэтому использовать его в прикладной логике нельзя.
Для начала создадим простую таблицу с первичным ключом и несколькими тестовыми записями, чтобы наглядно проследить, как изменяется значение ctid.
CREATE TABLE users (
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name TEXT
);
INSERT INTO users (name)
VALUES
('Alice'),
('Bob'),
('Charlie');
ctid PostgreSQL присвоил каждой записи после вставки.SELECT
ctid,
id,
name
FROM users;
ctid | id | name
------+----+--------
(0,1) | 1 | Alice
(0,2) | 2 | Bob
(0,3) | 3 | Charlie
UPDATE users
SET name = 'Robert'
WHERE id = 2;
UPDATE снова посмотрим значения ctid и сравним их с предыдущим результатом.SELECT
ctid,
id,
name
FROM users;
ctid изменилось. Например:ctid | id | name
------+----+---------
(0,1) | 1 | Alice
(0,4) | 2 | Robert
(0,3) | 3 | Charlie
UPDATE PostgreSQL не изменяет строку на месте, а создаёт её новую версию, которая получает новый физический адрес (ctid). Старая версия строки некоторое время остаётся в таблице и может быть видима другим транзакциям в зависимости от их снимка данных. ctid происходит не только при UPDATE. Любые операции, которые физически переписывают таблицу, также приводят к изменению физических адресов строк. Например:VACUUM FULL users;
CLUSTER users USING users_pkey;
ctid в качестве внешнего ключа, хранить его в приложении или считать постоянным идентификатором записи нельзя.ctid остаётся полезным инструментом для служебных задач. Один из самых распространённых случаев — удалить одну запись среди полностью одинаковых дубликатов, когда значения всех пользовательских столбцов совпадают и отличить строки обычными средствами невозможно.CREATE TABLE duplicate_users (
name TEXT
);
INSERT INTO duplicate_users (name)
VALUES
('Alice'),
('Alice'),
('Bob');
DELETE
FROM duplicate_users
WHERE ctid = (
SELECT ctid
FROM duplicate_users
WHERE name = 'Alice'
LIMIT 1
);
Alice. В этом примере ctid определяется и используется в рамках одного SQL-запроса, поэтому используется актуальный физический адрес версии строки и не возникает проблемы с использованием устаревшего значения.ctid — это физический адрес текущей версии строки, а не её постоянный идентификатор. Для связи данных всегда используйте первичный ключ, а ctid оставьте для диагностических и служебных операций.
🐱 Нашел крайне занимательную статью на Хабре: «Условная агрегация в SQL: ускоряем отчеты, избавляясь от лишних JOIN-ов и подзапросов»!
В этой статье:• Узнаете, как ускорять сложные SQL-запросы с помощью условной агрегации;• Разберёте применение CASE и FILTER вместо множества подзапросов и JOIN-ов;• Посмотрите на примерах, как сделать SQL-код быстрее, чище и проще для поддержки.
🔊 Продолжай читать на Habr!
Почему коррелированные подзапросы могут снижать производительность SQL-запроса!
Коррелированные подзапросы удобны: внутри них можно обращаться к значениям текущей строки внешнего запроса.
Проблема в том, что оптимизатор может выбрать план, при котором такой подзапрос будет выполняться повторно для каждой строки внешней выборки. На больших объёмах данных это может стать узким местом. Например:
SELECT
u.id,
u.name,
(
SELECT SUM(o.amount)
FROM orders o
WHERE o.user_id = u.id
) AS total_amount
FROM users u;
users содержит миллион строк, подзапрос потенциально может быть выполнен миллион раз. Даже при наличии индекса по orders.user_id такой подход иногда становится менее эффективным, особенно в сложных отчётах.SELECT
u.id,
u.name,
COALESCE(o.total_amount, 0) AS total_amount
FROM users u
LEFT JOIN (
SELECT
user_id,
SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
) o
ON o.user_id = u.id;
EXPLAIN / EXPLAIN ANALYZE.SELECT
user_id,
created_at
FROM (
SELECT
user_id,
created_at,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY created_at DESC
) AS rn
FROM orders
) t
WHERE rn = 1;
(user_id, created_at DESC)
SELECT ...
FROM orders
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT 1;
JOIN, предварительная агрегация или оконные функции позволяют значительно уменьшить количество лишних операций.
Научите оптимизатор понимать ваши данные!
PostgreSQL по умолчанию считает, что значения в разных колонках независимы друг от друга. Но в реальных данных это часто не так.
Например, если city = 'Paris', то country почти всегда будет 'France'. Без этой информации оптимизатор может сильно ошибиться при оценке количества строк и выбрать неудачный план.
EXPLAIN
SELECT *
FROM users
WHERE country = 'France'
AND city = 'Paris';
CREATE STATISTICS users_dep (dependencies)
ON country, city
FROM users;
ANALYZE users;
ANALYZE PostgreSQL сможет учитывать зависимость между колонками и точнее оценивать селективность условий. Во многих случаях этого достаточно, чтобы оптимизатор выбрал более эффективный план выполнения.CREATE STATISTICS, а уже потом решайте, нужен ли новый индекс.
Почему 5 систем могут потребовать 10 интеграций, а 10 — уже 45?
Когда в data stack появляется несколько отдельных инструментов для хранения, обработки и аналитики, между ними приходится выстраивать обмен данными. Для пяти систем таких связок может быть до 10, а для десяти — уже до 45.
Yandex B2B Tech представила DataLens Platform на основе архитектуры lakehouse. Исходные и подготовленные данные хранятся в общей среде на S3 с использованием Apache Iceberg.
Из технических деталей — storage и compute масштабируются независимо. То есть рост объема данных не обязательно означает пропорциональное увеличение вычислительных ресурсов, и наоборот.
👉 Подробнее об архитектуре DataLens Platform — в материале СМИ.
📂 Шпаргалка по SQL для разработчиков!
Например, SELECT используется для получения данных из таблиц, а CREATE, ALTER и DROP помогают управлять структурой базы данных. JOIN позволяет объединять данные из нескольких таблиц, а агрегатные функции (COUNT, SUM, AVG) — анализировать большие объёмы информации.
На картинке — шпаргалка с основными категориями команд, операторами, ключевыми словами, объектами базы данных, ограничениями, функциями агрегации, типами JOIN.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
🤔 MentorData — материалы по SQL и аналитике данных!
Авторский блог с материалами для тех, кто изучает SQL, аналитику данных и готовится к работе в этой сфере. Основной акцент сделан не только на синтаксисе, но и на решении аналитических задач и понимании бизнес-логики. В статьях разбираются оконные функции, JOIN, GROUP BY, CTE, работа с аномалиями и метриками, задачи с технических собеседований и подходы к анализу данных.
📌 Оставляю ссылочку: mentordata.ru
➡️ SQL Ready | #ресурс
🖥 Oracle — агрегация данных и отчётность!Шпаргалка по агрегации данных и формированию отчётности в Oracle SQL: объединение значений с LISTAGG, выбор значений по рангу с KEEP (DENSE_RANK FIRST/LAST), построение промежуточных и общих итогов с ROLLUP и GROUPING SETS, а также идентификация уровней агрегации с помощью GROUPING и GROUPING_ID. Полезно для построения сводных выборок, многоуровневых отчётов и обработки агрегированных данных непосредственно средствами SQL.
➡️ SQL Ready | #шпора
Оконный фрейм по группам значений!ROWS считает физические строки. GROUPS считает группы строк с одинаковым значением ORDER BY.
SELECT price,
count(*) OVER (
ORDER BY price
GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
FROM products;
dense_rank() и не добавляя ещё один уровень запроса.EXCLUDE, который можно использовать прямо внутри оконного фрейма:SELECT id,
avg(score) OVER (
ORDER BY created_at
ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING
EXCLUDE CURRENT ROW
) AS neighbors_avg
FROM measurements;
SELECT price,
sum(amount) OVER (
ORDER BY price
GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE GROUP
)
FROM sales;
EXCLUDE GROUP исключит из расчёта всю текущую peer-группу, а не только одну строку.GROUPS + EXCLUDE позволяют описывать сложные окна непосредственно в OVER, где обычно появляются dense_rank(), дополнительные CTE и self join.
📂 Шпаргалка по структурам данных!
Например, стек работает по принципу LIFO — последний добавленный элемент извлекается первым, а очередь наоборот использует FIFO — первым выходит тот, кто пришёл первым.
На картинке — 7 основных структур данных: массивы, связные списки, стек, очередь, хеш-таблица, дерево и граф. Полезная база, которую стоит знать каждому разработчику.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
Проверяйте преобразование без исключений!
Обычный cast падает с ошибкой, если значение нельзя преобразовать. Из-за этого в ETL и в запросах к промежуточным данным часто приходится заранее чистить данные или писать PL/pgSQL с обработкой исключений.
SELECT value::integer
FROM staging;
-- ERROR при первом плохом значении
SELECT value
FROM staging
WHERE pg_input_is_valid(value, 'integer');
integer:SELECT pg_input_is_valid('192.168.1.10', 'inet');
SELECT pg_input_is_valid('550e8400-e29b-41d4-a716-446655440000', 'uuid');
SELECT pg_input_is_valid('2026-09-08', 'date');pg_input_error_info() позволяет получить причину, почему преобразование невозможно.SELECT *
FROM pg_input_error_info('2026-02-30', 'date');
pg_input_is_valid() позволяет валидировать грязные входные данные средствами самой системы типов PostgreSQL.
😎 PostgreSQL FAQ — справочник по частым проблемам и вопросам!
Здесь собраны разборы типичных ситуаций при работе с PostgreSQL: проблемы с подключением и настройкой, ошибки в SQL, оптимизация медленных запросов, партиционирование, размеры таблиц, timestamp with time zone, pg_dump и другие нюансы. Есть конкретные команды, примеры диагностики и рекомендации по тому, какие данные собирать для поиска проблем.
Оставляю ссылочку: GitHub 📱
✍️ Попалась интересная статья на Хабре: «Почему в БД на PostgreSQL популярен тип numeric?»!
В этой статье:• Разберётесь, почему для денег и точных расчётов часто выбирают numeric, несмотря на его производительность;• Узнаете, чем на практике отличаются numeric, целые типы и double precision;• Посмотрите, какие требования к точности и округлению предъявляют SQL, платёжные системы и финансовые стандарты.
🔊 Продолжай читать на Habr!
📂 Шпаргалка по снижению Latency в Backend-системах!
Например, Cache позволяет отдавать часто используемые данные без обращения к базе данных, а Load Balancer распределяет запросы между несколькими серверами, повышая скорость и отказоустойчивость приложения.
На картинке — основные стратегии уменьшения задержек в высоконагруженных системах.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
🖥 MySQL — работа с NULL!Шпаргалка по обработке NULL в MySQL: подстановка резервных значений, проверка наличия и отсутствия данных, условная обработка, безопасные вычисления и сравнение nullable-значений. Помогает учитывать семантику NULL и избегать неочевидного поведения в условиях, выражениях и вычислениях.
➡️ SQL Ready | #шпора
7,2 млн рублей призового фонда и реальные задачи космической отрасли 🚀
В сентябре пройдет серия КосмоХакатонов для студентов, молодых ученых и специалистов.
Участникам предстоит за два дня разработать собственное решение, поработать с экспертами и представить проект жюри.
Участников ждут:
🛰 реальные задачи космической отрасли
👥 команды от 3 до 5 человек
💻 очный и онлайн-форматы
🧑💻 работа с экспертами и трекерами
🏆 финал в Москве
Первый КосмоХакатон стартует уже 4 сентября в Ростове-на-Дону.
Дальше серия продолжится в Красноярске, Нижнем Новгороде, Благовещенске и Санкт-Петербурге, а завершится финалом в Москве.
Участие бесплатное. Присоединиться могут студенты, аспиранты, молодые ученые и специалисты от 18 лет.
🔗 Зарегистрироваться: https://космохакатон.рф
✍️ Архитектура высоконагруженных систем — подробный материал по проектированию Highload!
Здесь разобраны ключевые вещи, с которыми сталкиваются при разработке нагруженных систем: RPS, latency и throughput, вертикальное и горизонтальное масштабирование, индексы, репликация и шардирование баз данных, кеширование, брокеры сообщений и др. Есть практические примеры с MySQL, PostgreSQL, Kafka и Tarantool, а также инструменты для тестирования и мониторинга.
Оставляю ссылочку: GitHub 📱
📂 Шпаргалка по Backend-разработке!
Например, REST используется для построения API, Redis помогает кэшировать данные, а Docker позволяет упаковать приложение вместе со всеми его зависимостями.
На картинке — основные направления Backend-разработки: языки программирования, базы данных, API, авторизация, серверы, контейнеризация, CI/CD и мониторинг. Полезная карта того, что стоит изучить Backend-разработчику.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
🤔 SQL Lab — интерактивная платформа для изучения и практики SQL!
Сайт для тех, кто хочет освоить SQL через работу с запросами. Код пишется прямо в браузере: выполняете запрос, сразу видите результат и получаете автоматическую проверку решения. Обучение построено от базовых SELECT и ORDER BY до JOIN, подзапросов, транзакций, индексов, оптимизации запросов и PostgreSQL. Есть структурированные курсы с теорией и практикой.
📌 Оставляю ссылочку: sqllab.ru
➡️ SQL Ready | #ресурс