Для больших наборов данных использование LIMIT + OFFSET работает не всегда эффективно, особенно если значение OFFSET большое.
Вместо этого можно применять постраничную выборку на основе курсора, где фильтрация идёт по значениям сортировки.
Именно поэтому сервисы вроде GitHub используют такой подход к пагинации
👉 @SQLPortal
Вместо этого можно применять постраничную выборку на основе курсора, где фильтрация идёт по значениям сортировки.
Именно поэтому сервисы вроде GitHub используют такой подход к пагинации
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍4🔥3
Нельзя понять производительность SQL-запроса просто по его коду. Для этого нужен план выполнения.
Пример:
Из этого кода не видно, как быстро выполнится запрос.
Если на колонке grade нет индекса, база сделает полное сканирование таблицы, и выполнение займёт несколько секунд в зависимости от числа строк.
Если добавить индекс на grade, тот же запрос выполнится быстрее.
Если сделать индекс покрывающим (добавить id как включённый столбец), то это будет уже index-only scan, и запрос станет ещё быстрее.
Если вставить миллион записей и сразу выполнить запрос (без работы сборщика мусора MVCC), он снова замедлится, так как нужно проверять видимость строк в heap.
Во всех этих случаях код на бэкенде не менялся — один и тот же запрос.
Но его производительность разная и зависит от состояния базы.
План выполнения показывает, как именно запрос исполнялся. Это ключ к пониманию.
👉 @SQLPortal
Пример:
select id from student where grade >= 99
Из этого кода не видно, как быстро выполнится запрос.
Если на колонке grade нет индекса, база сделает полное сканирование таблицы, и выполнение займёт несколько секунд в зависимости от числа строк.
Если добавить индекс на grade, тот же запрос выполнится быстрее.
Если сделать индекс покрывающим (добавить id как включённый столбец), то это будет уже index-only scan, и запрос станет ещё быстрее.
Если вставить миллион записей и сразу выполнить запрос (без работы сборщика мусора MVCC), он снова замедлится, так как нужно проверять видимость строк в heap.
Во всех этих случаях код на бэкенде не менялся — один и тот же запрос.
Но его производительность разная и зависит от состояния базы.
План выполнения показывает, как именно запрос исполнялся. Это ключ к пониманию.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤1
Будьте осторожны при фильтрации внутренней таблицы в OUTER JOIN.
Например, правой таблицы в LEFT OUTER JOIN.
Если применить фильтр к ней в секции WHERE, то соединение фактически превращается в INNER JOIN.
Чтобы сохранить именно OUTER JOIN, фильтровать внутреннюю таблицу нужно в секции ON.
На схеме показан OUTER JOIN по числовой колонке с внутренними фильтрами.
👉 @SQLPortal
Например, правой таблицы в LEFT OUTER JOIN.
Если применить фильтр к ней в секции WHERE, то соединение фактически превращается в INNER JOIN.
Чтобы сохранить именно OUTER JOIN, фильтровать внутреннюю таблицу нужно в секции ON.
На схеме показан OUTER JOIN по числовой колонке с внутренними фильтрами.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥3👍2
С oracle sql 25.2 теперь можно запускать MCP-серверы.
Они позволяют взаимодействовать с вашей Oracle Database через AI-агентов.
That Jeffsmith подготовил FAQ, который помогает понять, как это работает, включая:
• Работает ли это с 11g или 12c? Скорее всего, да
• Как сделать использование безопасным
👉 @SQLPortal
Они позволяют взаимодействовать с вашей Oracle Database через AI-агентов.
That Jeffsmith подготовил FAQ, который помогает понять, как это работает, включая:
• Работает ли это с 11g или 12c? Скорее всего, да
• Как сделать использование безопасным
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4
Работа с SQL на больших данных — опыт перехода с 4 млн на 42 млн клиентов
Разработчик поделился историей. В новой компании с 42 млн пользователей его первый SQL-запрос «упал». Масштаб данных потребовал изменить подход.
Что изменилось
I. Дробление запросов
Вместо монолитных SQL-скриптов в 500 строк используются промежуточные staging-таблицы, пошаговая логика и CTE. Это помогает базе работать стабильнее и быстрее.
II. Разделение данных
Огромная таблица заменена на две структуры
- Current содержит только актуальный срез для быстрых дашбордов
- History хранит полную историю для комплаенса
Так удалось сбалансировать скорость и полноту.
III. Точность требований
Формулировки вроде «дайте все данные» больше не работают. Теперь разработчик уточняет какой период нужен, какие сегменты важны, какой бизнес-вопрос стоит за задачей.
При работе с десятками миллионов клиентов важно дробить запросы, разделять данные на текущие и архивные и добиваться конкретных требований. Такой подход ускоряет аналитику и снижает нагрузку на базы.
👉 @SQLPortal
Разработчик поделился историей. В новой компании с 42 млн пользователей его первый SQL-запрос «упал». Масштаб данных потребовал изменить подход.
Что изменилось
I. Дробление запросов
Вместо монолитных SQL-скриптов в 500 строк используются промежуточные staging-таблицы, пошаговая логика и CTE. Это помогает базе работать стабильнее и быстрее.
II. Разделение данных
Огромная таблица заменена на две структуры
- Current содержит только актуальный срез для быстрых дашбордов
- History хранит полную историю для комплаенса
Так удалось сбалансировать скорость и полноту.
III. Точность требований
Формулировки вроде «дайте все данные» больше не работают. Теперь разработчик уточняет какой период нужен, какие сегменты важны, какой бизнес-вопрос стоит за задачей.
При работе с десятками миллионов клиентов важно дробить запросы, разделять данные на текущие и архивные и добиваться конкретных требований. Такой подход ускоряет аналитику и снижает нагрузку на базы.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍4
Внешние таблицы — отличный способ читать текстовые файлы в Oracle Database с помощью SQL.
Но что, если у тебя есть поля длиннее 4000 символов?
Anti Kyte разбирает:
I. Маппинг CHAR в ACCESS PARAMETERS на CLOB
II. Увеличение READSIZE
III. Использование big data driver
👉 @SQLPortal
Но что, если у тебя есть поля длиннее 4000 символов?
Anti Kyte разбирает:
I. Маппинг CHAR в ACCESS PARAMETERS на CLOB
II. Увеличение READSIZE
III. Использование big data driver
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3
У Postgres есть огромное преимущество перед MySQL в плане поддержки транзакций.
Большинство операторов CREATE, ALTER и DROP в Postgres являются полноценными участниками многооператорных транзакций. Это означает, что их можно использовать между BEGIN и COMMIT, и все изменения либо успешно применяются, либо откатываются атомарно вместе со всеми другими операторами.
В MySQL это не так. Подобные операторы работают по модели неявного коммита: при выполнении CREATE, ALTER или DROP происходит автоматический коммит текущей транзакции.
Таким образом, в Postgres можно, например:
- создать таблицу и вставить в неё данные в рамках одного атомарного действия,
- атомарно изменить несколько таблиц.
👉 @SQLPortal
Большинство операторов CREATE, ALTER и DROP в Postgres являются полноценными участниками многооператорных транзакций. Это означает, что их можно использовать между BEGIN и COMMIT, и все изменения либо успешно применяются, либо откатываются атомарно вместе со всеми другими операторами.
В MySQL это не так. Подобные операторы работают по модели неявного коммита: при выполнении CREATE, ALTER или DROP происходит автоматический коммит текущей транзакции.
Таким образом, в Postgres можно, например:
- создать таблицу и вставить в неё данные в рамках одного атомарного действия,
- атомарно изменить несколько таблиц.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤5👍2
Нашёлся интересный ресурс для тех, кто готовится к техническим собеседованиям: на нём собрано очень много практических SQL-вопросов из самых разных областей.
Есть задачи на работу с запросами, оптимизацию, подзапросы, агрегации и даже отдельный блок, посвящённый вопросам, встречающимся в интервью у компаний уровня FAANG.🥸
👉 @SQLPortal
Есть задачи на работу с запросами, оптимизацию, подзапросы, агрегации и даже отдельный блок, посвящённый вопросам, встречающимся в интервью у компаний уровня FAANG.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Консистентность «read-your-writes» означает, что любая запись, сделанная в базу данных, сразу становится доступной для чтения тем же клиентом.
Звучит очевидно, но бывают ситуации, когда это правило не выполняется, особенно при работе на больших масштабах.
На сервере с одной нодой это легко гарантировать при использовании последовательных транзакций.
В среде с primary и replica всё сложнее. Во многих базах данных все записи и часть чтений обрабатываются на primary, а большая часть чтений выполняется на репликах. Из-за задержки репликации может возникнуть ситуация, когда клиент записывает данные в базу и тут же пытается их прочитать с реплики, но записи там ещё нет.
Такое возможно при использовании асинхронной или полусинхронной репликации, так как они не требуют, чтобы все реплики получили данные до ответа клиенту. При синхронной репликации primary отвечает только после того, как все реплики подтвердят получение записи.
Если используется асинхронная или полусинхронная репликация, чтения на реплики лучше направлять только тогда, когда консистентность «read-your-writes» не критична.
👉 @SQLPortal
Звучит очевидно, но бывают ситуации, когда это правило не выполняется, особенно при работе на больших масштабах.
На сервере с одной нодой это легко гарантировать при использовании последовательных транзакций.
В среде с primary и replica всё сложнее. Во многих базах данных все записи и часть чтений обрабатываются на primary, а большая часть чтений выполняется на репликах. Из-за задержки репликации может возникнуть ситуация, когда клиент записывает данные в базу и тут же пытается их прочитать с реплики, но записи там ещё нет.
Такое возможно при использовании асинхронной или полусинхронной репликации, так как они не требуют, чтобы все реплики получили данные до ответа клиенту. При синхронной репликации primary отвечает только после того, как все реплики подтвердят получение записи.
Если используется асинхронная или полусинхронная репликация, чтения на реплики лучше направлять только тогда, когда консистентность «read-your-writes» не критична.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Вышел бесплатный онлайн-плейграунд для SQL — RunSQL.
Сервис позволяет создавать таблицы, писать запросы и делиться результатами с командой. Поддерживаются MySQL, PostgreSQL и SQL Server.
Работает прямо из браузера, ничего устанавливать не нужно: https://runsql.com/r
👉 @SQLPortal
Сервис позволяет создавать таблицы, писать запросы и делиться результатами с командой. Поддерживаются MySQL, PostgreSQL и SQL Server.
Работает прямо из браузера, ничего устанавливать не нужно: https://runsql.com/r
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍2
Индексы covering дают серьезный прирост производительности, если использовать их правильно
Covering index это индекс, который покрывает все колонки, нужные для результата запроса, без обращения к основной таблице. В Postgres это значит, что можно обойтись без table heap, а в MySQL без обращения к clustered index данных таблицы
Например, запрос:
Если есть индекс только по
База сможет использовать индекс для фильтрации, но всё равно придется искать email в основной таблице
Если же создать составной индекс
То все нужные колонки уже есть в индексе, и запрос отрабатывает быстрее
Минус в том, что индекс становится больше. Классический компромисс между пространством и временем
👉 @SQLPortal
Covering index это индекс, который покрывает все колонки, нужные для результата запроса, без обращения к основной таблице. В Postgres это значит, что можно обойтись без table heap, а в MySQL без обращения к clustered index данных таблицы
Например, запрос:
SELECT name, email
FROM user
WHERE name > 'C' AND name < 'G';
Если есть индекс только по
nameCREATE INDEX idx_name
ON your_table (name);
База сможет использовать индекс для фильтрации, но всё равно придется искать email в основной таблице
Если же создать составной индекс
CREATE INDEX idx_name_email
ON your_table (name, email);
То все нужные колонки уже есть в индексе, и запрос отрабатывает быстрее
Минус в том, что индекс становится больше. Классический компромисс между пространством и временем
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍1
Простое объяснение соединений в базах данных:
Соединения позволяют связывать разные таблицы на основе их отношений.
Они особенно полезны, когда нужно получить данные из нескольких таблиц одновременно.
Основные типы соединений:
1. Inner Join – возвращает только те строки, которые совпадают в обеих таблицах.
2. Left (Outer) Join – возвращает все строки из левой таблицы и только совпадающие строки из правой.
Другие виды соединений:
- Self Join – соединение таблицы самой с собой.
- Outer Join – включает все строки из обеих таблиц с учетом совпадений и неполных данных.
- Cross Join – декартово произведение двух таблиц, каждая строка первой таблицы соединяется со всеми строками второй.
👉 @SQLPortal
Соединения позволяют связывать разные таблицы на основе их отношений.
Они особенно полезны, когда нужно получить данные из нескольких таблиц одновременно.
Основные типы соединений:
1. Inner Join – возвращает только те строки, которые совпадают в обеих таблицах.
2. Left (Outer) Join – возвращает все строки из левой таблицы и только совпадающие строки из правой.
Другие виды соединений:
- Self Join – соединение таблицы самой с собой.
- Outer Join – включает все строки из обеих таблиц с учетом совпадений и неполных данных.
- Cross Join – декартово произведение двух таблиц, каждая строка первой таблицы соединяется со всеми строками второй.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤4🤯2
Фича Postgres 18: дамп статистики таблиц
В Postgres 18 появится возможность использовать
👉 @SQLPortal
В Postgres 18 появится возможность использовать
pg_dump --statistics-only и --with-statisticsPlease open Telegram to view this post
VIEW IN TELEGRAM
👍6
Если ты пишешь сложные вложенные подзапросы, лучше использовать CTE , чтобы улучшить читаемость
CTE позволяет определить запрос и работать с его результатом как с новой таблицей, организуя логику в иерархическую структуру.
@SQLPortal
CTE позволяет определить запрос и работать с его результатом как с новой таблицей, организуя логику в иерархическую структуру.
@SQLPortal
❤15😁4👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Новый уровень баз данных
Turso это впечатляющий технический проект. Это переписанный на Rust SQLite с архитектурой async-first, готовящейся поддержкой конкурентных записей, векторным поиском и встроенной поддержкой браузера / WASM.
Есть все шансы, что он станет фундаментальной частью инфраструктуры «vibe-coding» эпохи: on-demand, глобальные базы данных, совместимые с SQLite, которые можно запускать как в браузере, так и локально на устройстве.
Скорость, с которой развивается проект, это явно что-то необычное.🐱
Демо: shell.turso.tech
@SQLPortal
Turso это впечатляющий технический проект. Это переписанный на Rust SQLite с архитектурой async-first, готовящейся поддержкой конкурентных записей, векторным поиском и встроенной поддержкой браузера / WASM.
Есть все шансы, что он станет фундаментальной частью инфраструктуры «vibe-coding» эпохи: on-demand, глобальные базы данных, совместимые с SQLite, которые можно запускать как в браузере, так и локально на устройстве.
Скорость, с которой развивается проект, это явно что-то необычное.
Демо: shell.turso.tech
@SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
PostgreSQL получил полезное обновление для разработчиков
Теперь блокировка FOR NO KEY UPDATE официально помогает избегать проблем с параллельной вставкой в дочерние таблицы.
Ранее использование классического FOR UPDATE на родительской записи могло блокировать добавление связанных строк, например комментариев к посту. С FOR NO KEY UPDATE родительскую запись можно защищать от изменений, не мешая вставке дочерних данных. Это ускоряет работу баз и повышает параллельность операций, особенно в сложных схемах с внешними ключами.
Подробнее о механике и примерах использования можно почитать на блоге Владислава Михалчева
👉 @SQLPortal
Теперь блокировка FOR NO KEY UPDATE официально помогает избегать проблем с параллельной вставкой в дочерние таблицы.
Ранее использование классического FOR UPDATE на родительской записи могло блокировать добавление связанных строк, например комментариев к посту. С FOR NO KEY UPDATE родительскую запись можно защищать от изменений, не мешая вставке дочерних данных. Это ускоряет работу баз и повышает параллельность операций, особенно в сложных схемах с внешними ключами.
Подробнее о механике и примерах использования можно почитать на блоге Владислава Михалчева
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4
Объединяем строки по значению в SQL
Для этого используется GROUP BY col.
Он возвращает по одной строке для каждого уникального значения в колонке col.
После этого можно применять агрегатные функции, чтобы получить сводные данные по каждой группе:
COUNT — количество строк
AVG — среднее числовое значение
MIN/MAX — минимальное и максимальное значения
LISTAGG — список значений
Простой способ быстро агрегировать данные и видеть сводную информацию по каждой группе.
@SQLPortal
Для этого используется GROUP BY col.
Он возвращает по одной строке для каждого уникального значения в колонке col.
После этого можно применять агрегатные функции, чтобы получить сводные данные по каждой группе:
COUNT — количество строк
AVG — среднее числовое значение
MIN/MAX — минимальное и максимальное значения
LISTAGG — список значений
Простой способ быстро агрегировать данные и видеть сводную информацию по каждой группе.
@SQLPortal
❤4👍4
Совет для psql:
Часто вы подключаетесь к базе данных в схеме по умолчанию или в public. Команда
Схема является частью поискового пути psql (search_path), поэтому чтобы сменить схему, нужно изменить поисковый путь:
👉 @SQLPortal
\dn — показывает все схемы.Часто вы подключаетесь к базе данных в схеме по умолчанию или в public. Команда
\dn позволяет увидеть другие схемы.Схема является частью поискового пути psql (search_path), поэтому чтобы сменить схему, нужно изменить поисковый путь:
SET search_path TO new_schema;
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Функция NVL в Oracle SQL возвращает:
первый аргумент, если он не NULL
иначе — второй аргумент
Пример использования:
План выполнения может использовать индекс, если
и
Демо у Monika Mitura
@SQLPortal
первый аргумент, если он не NULL
иначе — второй аргумент
Пример использования:
WHERE col = NVL(:var, col)
План выполнения может использовать индекс, если
:var не NULL,и
full table scan, если :var равен NULL.Демо у Monika Mitura
@SQLPortal
Blogspot
The Magical NVL Function
A while ago, I came across an interesting NVL trick on Connor Mc'Donald's blog . In his example, he compares a query that uses an optiona...
👍6
Полный курс по SQL от основ до продвинутого уровня
Репозиторий SQL-Tutorials от разработчика GowthamRaj K представляет собой обширный ресурс для изучения SQL, идеально подходящий для начинающих и тех, кто хочет систематизировать свои знания.
👉 @SQLPortal
Репозиторий SQL-Tutorials от разработчика GowthamRaj K представляет собой обширный ресурс для изучения SQL, идеально подходящий для начинающих и тех, кто хочет систематизировать свои знания.
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - gowthamrajk/SQL-Tutorials: In this module, I will be updating the topic wise SQL tutorial notes which is very useful for…
In this module, I will be updating the topic wise SQL tutorial notes which is very useful for a fresher to start with MYSQL from basics to advanced. - gowthamrajk/SQL-Tutorials
👍7❤3