Чтиво на выходные для амбициозных ребят 🔥
Полноценная книга по архитектуре БД
Как проектировать базы с помощью SQL и реляционных СУБД. Для новичков, с Jupyter Notebook для практики. Освоите Postgres и основы SQL, научитесь проектировать и поддерживать безопасные и эффективные БД для сложных приложений.
> Читать книгу
👉 @SQLPortal
Полноценная книга по архитектуре БД
Как проектировать базы с помощью SQL и реляционных СУБД. Для новичков, с Jupyter Notebook для практики. Освоите Postgres и основы SQL, научитесь проектировать и поддерживать безопасные и эффективные БД для сложных приложений.
> Читать книгу
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍2
Два SQL-запроса ниже для планировщика разные:
Планировщику нужно разобрать скомпилировать и построить план для каждого
Использование bind-переменных позволяет избежать парсинга
Теперь оба хешируются в один и тот же план:
Из этого вылезают любопытные ситуации:
может использовать индекс по id благодаря высокой избирательности, но повторное применение того же индексного плана для
может быть не таким эффективным как полный скан
Ничего не бывает бесплатным. Всегда есть компромисс
👉 @SQLPortal
select * from emp where id = 7
select * from emp where id = 9
Планировщику нужно разобрать скомпилировать и построить план для каждого
Использование bind-переменных позволяет избежать парсинга
Теперь оба хешируются в один и тот же план:
select * from emp where id = ?, 7
select * from emp where id = ?, 9
Из этого вылезают любопытные ситуации:
select * from emp where id between ? and ?, 1, 3
может использовать индекс по id благодаря высокой избирательности, но повторное применение того же индексного плана для
select * from emp where id between ? and ?, 0, 9000000
может быть не таким эффективным как полный скан
Ничего не бывает бесплатным. Всегда есть компромисс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Хочешь попрактиковаться в SQL на реальных задачах от топовых компаний и подготовиться к собеседованиям?
Заходи на stratascratch.com — там собраны сотни задач с интервью в FAANG и других крупных компаниях
Удобный онлайн-редактор, проверка решений и пояснения помогут прокачать скилл без лишней мороки🤩
👉 @SQLPortal
Заходи на stratascratch.com — там собраны сотни задач с интервью в FAANG и других крупных компаниях
Удобный онлайн-редактор, проверка решений и пояснения помогут прокачать скилл без лишней мороки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4
Если ты запускаешь транзакцию в уровне изоляции Read Committed (назовём её tx1) и выполняешь долгий SELECT — например, с сортировками и join’ами по большим датасетам — база берёт снимок зафиксированных данных на момент старта этого запроса.
Пока этот SELECT ещё работает, другая транзакция (tx2) в другом сеансе обновляет те же строки и успевает закоммитить.
Несмотря на то что tx2 закоммитила во время выполнения SELECT, твой запрос внутри tx1 этих апдейтов не увидит, потому что каждый запрос в Read Committed использует снимок данных, сделанный в начале его выполнения. Всё, что было зафиксировано после старта запроса, отфильтровывается.
Но если потом в рамках tx1 ты запустишь ещё один SELECT, он уже увидит изменения из tx2, так как возьмёт новый снимок, включающий все коммиты, сделанные к этому моменту.
В Postgres этот снимок строится на основе идентификаторов транзакций.
👉 @SQLPortal
Пока этот SELECT ещё работает, другая транзакция (tx2) в другом сеансе обновляет те же строки и успевает закоммитить.
Несмотря на то что tx2 закоммитила во время выполнения SELECT, твой запрос внутри tx1 этих апдейтов не увидит, потому что каждый запрос в Read Committed использует снимок данных, сделанный в начале его выполнения. Всё, что было зафиксировано после старта запроса, отфильтровывается.
Но если потом в рамках tx1 ты запустишь ещё один SELECT, он уже увидит изменения из tx2, так как возьмёт новый снимок, включающий все коммиты, сделанные к этому моменту.
В Postgres этот снимок строится на основе идентификаторов транзакций.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11
This media is not supported in your browser
VIEW IN TELEGRAM
Copilot как функция в Excel
Microsoft только что анонсировала функцию copilot в Excel
Новая функция =COPILOT() в Excel позволяет анализировать данные, генерировать контент и брейнштормить прямо в ячейках таблицы
Подробнее: ссылка
👉 @SQLPortal
Microsoft только что анонсировала функцию copilot в Excel
Новая функция =COPILOT() в Excel позволяет анализировать данные, генерировать контент и брейнштормить прямо в ячейках таблицы
Подробнее: ссылка
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤4
Ряды, которые возвращают основные типы SQL-джоинов
🔸 INNER
Ряды, где значения по колонке соединения совпадают в обеих таблицах
🔸 OUTER
Все ряды из внешней таблицы плюс совпадающие ряды из внутренней. FULL OUTER JOIN сохраняет ряды из обеих таблиц
🔸 CROSS
Каждая строка комбинируется с каждой другой
👉 @SQLPortal
Ряды, где значения по колонке соединения совпадают в обеих таблицах
Все ряды из внешней таблицы плюс совпадающие ряды из внутренней. FULL OUTER JOIN сохраняет ряды из обеих таблиц
Каждая строка комбинируется с каждой другой
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤3
Строки, которые возвращают операторов множеств в SQL:
🔸
Все строки из обеих таблиц
🔸
Строки из первой таблицы, которых нет во второй
🔸
Строки, которые есть в обеих таблицах одновременно
По умолчанию эти операторы убирают дубликаты.
Клаузa
👉 @SQLPortal
UNION
Все строки из обеих таблиц
MINUS
/ EXCEPT
Строки из первой таблицы, которых нет во второй
INTERSECT
Строки, которые есть в обеих таблицах одновременно
По умолчанию эти операторы убирают дубликаты.
Клаузa
ALL
сохраняет и учитывает дубликаты.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Проверка производительности Postgres:
Если вы держите базу на SSD, то дефолтные настройки Postgres замедляют вас.
В Postgres есть параметр
Планировщик запросов Postgres подбирает наиболее эффективный способ выполнить SQL-запрос. Он делает это, оценивая «стоимость» разных планов выполнения и выбирая тот, у которого общая стоимость ниже.
Представим, что вам нужно найти несколько конкретных товаров в большом супермаркете. Есть два варианта:
- sequential scan
Это как пройтись по каждому ряду магазина подряд от начала до конца. В Postgres это последовательное сканирование. Предсказуемо, между товарами минимум времени.
- index scan
Это как посмотреть в каталог магазина (индекс), найти номер ряда для каждого товара и сразу идти туда. Это индексное сканирование.
🔸 Высокий random_page_cost
Это говорит планировщику, что переходы между рядами очень затратные.
В итоге он чаще выберет sequential scan, даже если нужно всего несколько товаров, потому что так он «экономит» на случайных переходах.
🔸 Низкий random_page_cost
Это говорит планировщику, что переходы между рядами быстрые.
Тогда он охотнее использует index scan, так как выборочные переходы стоят дешево.
🔸 Значения по умолчанию
По умолчанию
Это означает, что случайное чтение страницы считается в 4 раза дороже последовательного.
Это консервативное значение под традиционные HDD.
На SSD или если база целиком помещается в RAM, штраф за случайные чтения намного ниже.
Индексные сканирования быстрее, и «переходы по рядам» дешевле.
Для SSD обычно лучше ставить значение от 1.1 до 1.5.
Последовательное сканирование использует другой параметр
Но так как итоговые стоимости планов зависят от относительной разницы этих двух параметров, обычно достаточно менять только
👉 @SQLPortal
random_page_cost
Если вы держите базу на SSD, то дефолтные настройки Postgres замедляют вас.
В Postgres есть параметр
random_page_cost
, который говорит планировщику запросов, насколько дорого читать случайную страницу с диска по сравнению с последовательным чтением. Планировщик запросов Postgres подбирает наиболее эффективный способ выполнить SQL-запрос. Он делает это, оценивая «стоимость» разных планов выполнения и выбирая тот, у которого общая стоимость ниже.
Представим, что вам нужно найти несколько конкретных товаров в большом супермаркете. Есть два варианта:
- sequential scan
Это как пройтись по каждому ряду магазина подряд от начала до конца. В Postgres это последовательное сканирование. Предсказуемо, между товарами минимум времени.
- index scan
Это как посмотреть в каталог магазина (индекс), найти номер ряда для каждого товара и сразу идти туда. Это индексное сканирование.
random_page_cost
отражает цену перехода между разными, несмежными рядами. Это говорит планировщику, что переходы между рядами очень затратные.
В итоге он чаще выберет sequential scan, даже если нужно всего несколько товаров, потому что так он «экономит» на случайных переходах.
Это говорит планировщику, что переходы между рядами быстрые.
Тогда он охотнее использует index scan, так как выборочные переходы стоят дешево.
По умолчанию
random_page_cost = 4.0
. Это означает, что случайное чтение страницы считается в 4 раза дороже последовательного.
Это консервативное значение под традиционные HDD.
На SSD или если база целиком помещается в RAM, штраф за случайные чтения намного ниже.
Индексные сканирования быстрее, и «переходы по рядам» дешевле.
Для SSD обычно лучше ставить значение от 1.1 до 1.5.
Последовательное сканирование использует другой параметр
seq_page_cost
, который по умолчанию равен 1.0. Но так как итоговые стоимости планов зависят от относительной разницы этих двух параметров, обычно достаточно менять только
random_page_cost
. Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤6
🎓 Курс “MongoDB для разработчиков”
1 сентября стартует обучение, которое поможет вам освоить одну из самых востребованных NoSQL-баз данных для современных приложений.
📌 На курсе вы:
научитесь создавать и администрировать базы и коллекции;
проектировать схемы без антипаттернов;
работать с индексами и агрегацией;
настраивать репликацию, шардинг и обеспечивать масштабируемость;
интегрировать MongoDB в CI/CD, Docker, Kubernetes и Terraform;
внедрять практики безопасности и мониторинга.
💡 Особенность курса — практические задания с рецензированием:
проверка ваших решений и обратная связь от преподавателей;
развитие навыков code review;
командные практики, приближенные к условиям реальной разработки.
🔖 По окончании курса вы получите именной сертификат, подтверждающий ваши навыки работы с MongoDB.
👨💻 Курс подходит backend- и web-разработчикам, аналитикам и всем, кто хочет уверенно перейти от реляционных БД к современным NoSQL-технологиям.
🚀 По промокоду MONGODB действует скидка 25 % в течение 24 часов
📅 Старт обучения: 1 сентября
📍 Формат: онлайн
👉 Записаться на курс
1 сентября стартует обучение, которое поможет вам освоить одну из самых востребованных NoSQL-баз данных для современных приложений.
📌 На курсе вы:
научитесь создавать и администрировать базы и коллекции;
проектировать схемы без антипаттернов;
работать с индексами и агрегацией;
настраивать репликацию, шардинг и обеспечивать масштабируемость;
интегрировать MongoDB в CI/CD, Docker, Kubernetes и Terraform;
внедрять практики безопасности и мониторинга.
💡 Особенность курса — практические задания с рецензированием:
проверка ваших решений и обратная связь от преподавателей;
развитие навыков code review;
командные практики, приближенные к условиям реальной разработки.
🔖 По окончании курса вы получите именной сертификат, подтверждающий ваши навыки работы с MongoDB.
👨💻 Курс подходит backend- и web-разработчикам, аналитикам и всем, кто хочет уверенно перейти от реляционных БД к современным NoSQL-технологиям.
🚀 По промокоду MONGODB действует скидка 25 % в течение 24 часов
📅 Старт обучения: 1 сентября
📍 Формат: онлайн
👉 Записаться на курс
🔥4💊3😁2
This media is not supported in your browser
VIEW IN TELEGRAM
Это сайт с ретро‑игровым туториалом, где SQL учишь прямо в браузере, используя DuckDB. Всё интерактивно, весело, и можно сразу пробовать запросы - без установки сервера, без настройки. 🙂
https://dbquacks.com/
👉 @SQLPortal
https://dbquacks.com/
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤4
В MySQL и Postgres есть несколько режимов репликации.
Один вариант — асинхронная репликация. Primary фиксирует транзакции и сразу отвечает клиенту, не дожидаясь подтверждения от реплик. Быстро, но с риском потери данных при отказе primary
Противоположность — синхронная репликация. Primary принимает запись, рассылает её всем фолловерам и ждёт, пока они закоммитят и пришлют ack. Только потом отправляет ответ. Такой режим даёт максимальную надёжность и консистентность, но замедляет запись.
Есть и промежуточный вариант — полусинхронная репликация. Primary ждёт ответа только от первой реплики (или первых N реплик), после чего отвечает клиенту. Можно ждать не полный commit, а лишь запись в лог. Это компромисс между скоростью и сохранностью данных.
Здесь приведены термины из MySQL, но в Postgres похожее можно настроить через параметры
В итоге выбор зависит от ваших приоритетов: важнее ли скорость записи или устойчивость и консистентность данных.
👉 @SQLPortal
Один вариант — асинхронная репликация. Primary фиксирует транзакции и сразу отвечает клиенту, не дожидаясь подтверждения от реплик. Быстро, но с риском потери данных при отказе primary
Противоположность — синхронная репликация. Primary принимает запись, рассылает её всем фолловерам и ждёт, пока они закоммитят и пришлют ack. Только потом отправляет ответ. Такой режим даёт максимальную надёжность и консистентность, но замедляет запись.
Есть и промежуточный вариант — полусинхронная репликация. Primary ждёт ответа только от первой реплики (или первых N реплик), после чего отвечает клиенту. Можно ждать не полный commit, а лишь запись в лог. Это компромисс между скоростью и сохранностью данных.
Здесь приведены термины из MySQL, но в Postgres похожее можно настроить через параметры
synchronous_standby_names
и synchronous_commit
В итоге выбор зависит от ваших приоритетов: важнее ли скорость записи или устойчивость и консистентность данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4
Клауза
Затем функция возвращает накопительный итог в рамках окна
Это включает все строки, у которых значение сортировки меньше либо равно значению текущей строки.
👉 @SQLPortal
ORDER BY
в оконных функциях SQL сортирует строки.Затем функция возвращает накопительный итог в рамках окна
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
Это включает все строки, у которых значение сортировки меньше либо равно значению текущей строки.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Апдейт Postgres 18: индексируемые UUID
Postgres 18 сейчас в бете и выйдет в продакшен этой осенью.
В
UUID — это случайно сгенерированные строки, которые по определению глобально уникальны.
Почему UUID хороши для первичных ключей
1. Уникальность — можно генерировать ключи в разных местах.
2. Развязка — приложение может создать первичный ключ ещё до того, как отправит данные в БД.
3. Безопасность — если в URL используются ID (
С UUID (
Что изменилось
- Раньше в Postgres нативно поддерживался UUIDv4, но сортировка и индексация в больших таблицах работала медленно.
- UUIDv7 решает проблему сортировки и индексации.
Он по-прежнему случайный, но первые 48 бит (12 символов) — это таймстамп, остальные биты остаются случайными.
Таймстамп
Таймстамп хранится в hex (по сути сжатое десятичное число).
Пример:
что соответствует количеству миллисекунд с 1970 года.
Пример DDL для UUIDv7
Если раньше у тебя были проблемы с UUID -сейчас можно уже попробовать бету
👉 @SQLPortal
Postgres 18 сейчас в бете и выйдет в продакшен этой осенью.
В
uuid
добавили поддержку UUIDv7. UUID — это случайно сгенерированные строки, которые по определению глобально уникальны.
Почему UUID хороши для первичных ключей
1. Уникальность — можно генерировать ключи в разных местах.
2. Развязка — приложение может создать первичный ключ ещё до того, как отправит данные в БД.
3. Безопасность — если в URL используются ID (
.../users/5
), атакующий легко подберёт другие (.../users/6
, .../users/7
) и увидит общее количество пользователей. С UUID (
.../users/f47ac10b-58cc-4372-a567-0e02b2c3d479
) такое невозможно. Что изменилось
- Раньше в Postgres нативно поддерживался UUIDv4, но сортировка и индексация в больших таблицах работала медленно.
- UUIDv7 решает проблему сортировки и индексации.
Он по-прежнему случайный, но первые 48 бит (12 символов) — это таймстамп, остальные биты остаются случайными.
Таймстамп
Таймстамп хранится в hex (по сути сжатое десятичное число).
Пример:
0189d6e4a5d6
(hex) = 2707238289622
(decimal), что соответствует количеству миллисекунд с 1970 года.
Пример DDL для UUIDv7
CREATE TABLE user_actions (
action_id UUID PRIMARY KEY DEFAULT uuidv7(),
user_id BIGINT NOT NULL,
action_description TEXT,
action_time TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Если раньше у тебя были проблемы с UUID -сейчас можно уже попробовать бету
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2