Oracle Developer👨🏻‍💻
3.27K subscribers
747 photos
105 videos
2 files
632 links
🔝 канал о разработке в СУБД Oracle:
SQL, PL/SQL, оптимизация, архитектура и многое другое...

Backend-pro.ru - обучение по различным программам, связанных с backend-разработкой для ФЛ и ЮЛ.

Основатель: @denis_dbd Кивилёв Денис
Помощница: @love_flowerrr
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Зачем нужен Index Skip Scan? Продолжение

Друзья, всем привет! 👋
С вами Костя Андронов 🙂

В понедельник мы опубликовали вопрос про Index Skip Scan от одного из наших студентов с 6 потока по оптимизации

Что такое Index Skip Scan?🤔

Это один из методов доступа к данным через индекс. Обычно он используется, когда в таблице есть составной индекс, но в предикатах запроса отсутствуют лидирующие колонки.

Рассмотрим на примере. Пусть у нас есть таблица employees и индекс:
create index emp_name_ix on employees(last_name, first_name)


Как выглядят листовые блоки этого индекса?

В них хранятся все пары last_name, first_name в отсортированном виде, и для каждой — rowid строки. Пример:
...
'Ivanov', 'Alexander' - 'AAAR2TAAUAAAADtAAD'
'Ivanov', 'Michail' - 'AAAR2TAAUAAAADtAAz'
...
'Petrov', 'Alexander' - 'AAAR2TAAUAAAADtAAF'
'Petrov', 'Petr' - 'AAAR2TAAUAAAADtABB'
...


А теперь вопрос: как получить только те строки, где first_name = 'Alexander'?

Есть два пути:
🔹 Прочитать весь индекс и отобрать нужное.
🔹 Перебирать возможные значения last_name, подставлять их в комбинации и искать пары (last_name, first_name) — то есть ключ индекса.

И вот второй вариант как раз и называется Index Skip Scan. Подробнее — в этом посте.

В чем же проблемы такого подхода?
Всё зависит от количества строк и уникальных значений в last_name.
🔸 Если уникальных значений немного — Skip Scan может быть выгодным.
🔸 Если их много — придётся выполнять массу сканирований индекса, и тут уже проще прочитать весь индекс или даже таблицу.

А в чем подвох?⚡️
Чтобы составной индекс работал эффективнее, лидирующие колонки должны быть высококардинальными. Другими словами уникальных значений last_name обычно очень много — и тогда появление Index Skip Scan в плане превращается в «узкое горлышко» в плане запроса

Для тех кто хочет разобраться в нюансах оптимизации и не знает с чего начать - Анкета предзаписи на 7 поток по оптимизации

С вами был Костя Андронов. Всем отличного дня и приятного просмотра! 🚀

#oracle #оптимизация #index #sql #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
🔥12👍74
This media is not supported in your browser
VIEW IN TELEGRAM
Происшествие с индексом

Друзья, всем привет! 👋
С вами Костя Андронов.

Сегодня разберём интересную ситуацию, которую я показывал на одной из практик курса «Оптимизация Oracle SQL».

Есть табличка employee1, у неё есть индекс по колонке department_id.

Пишем простой запрос:
select ...
from employee1 e
where department_id = 11;


Селективность этого предиката - 1,6% от общего количества строк в таблице.

Помните правило: индекс обычно используется, когда выбирается менее 15% строк.
В нашем случае 1,6% - прямо идеальные условия для применения индекса! ⚙️

Но если заглянуть в план выполнения, то видим неожиданное - Table Access Full 😱
Получается, индекс есть, но СУБД всё равно делает полный просмотр таблицы. Почему так происходит? 🤔

Кстати, отличный вопрос для собеседования 😉

Ответ кроется в нюансах оптимизатора Oracle, который иногда решает, что полное сканирование будет быстрее, чем обращение к индексу.

Почему так - разберём в четверг 🎓
Пишите ваши гипотезы в чатик 💬

Всем продуктивной рабочей недели! 💪

#oracle #performance #sql #оптимизация #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
🔥103👍2🤩2
Media is too big
VIEW IN TELEGRAM
Квантовый скачок, который мог быть быстрее

Друзья, всем привет! 👋
Денис на связи.

Хочу рассказать вам одну историю из своего студенчества. Когда я учился в университете, всё давалось нелегко, а особенно программирование. Почти полтора года я мучился с заданиями: то не понимал, как подступиться, то просто сдавал чужие работы, а иногда даже заказывал проекты, когда совсем не знал, с чего начать 🙈

И вот на 2м курсе поменялся препод и началось ООП, в голове что-то щёлкнуло. Всё, что я раньше учил, пробовал, ошибался — вдруг сложилось в систему. Накопленные знания превратились в осознанное понимание. Наступил тот самый квантовый скачок, когда начинаешь видеть, как всё взаимосвязано: логика, циклы, рекурсия, функции, программный код. С этого момента учёба перестала быть хаосом и стала осмысленным процессом 🚀

Кстати, если у вас была такая же история поделитесь в чатике. Будет интересно почитать 😉

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

📚 Хороший наставник не решает всё за ученика, а направляет — показывает, где искать ответы и как думать системно. Он помогает пройти через моменты, когда кажется, что ничего не получается. Именно тогда и рождается настоящее понимание.

Так что если вы чувствуете, что «застряли» — не спешите сдаваться. Это не тупик, а момент роста. Главное — не останавливаться и искать смысл в процессе.

Всем хорошего дня! 👍🏻

#обучение #наставник #программирование
#oracle #performance #sql #оптимизация #Denis_Kivilev

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
👍16🔥104
This media is not supported in your browser
VIEW IN TELEGRAM
Происшествие с индексом. Ответ

Друзья, всем привет! 👋
С вами Костя Андронов 🙂

В понедельник мы опубликовали пост с интересной ситуацией, которую я показывал на одной из практик курса «Оптимизация Oracle SQL».

Несмотря на идеальные условия для применения индекса (селективность предиката — всего 1,6%), Oracle выбирает Table Access Full вместо Index Range Scan 😱

Разбираемся, почему это произошло.

📌 Как Oracle выбирает метод доступа к данным?

На этапе hard-parse оптимизатор строит планы с разными методами доступа и оценивает их «стоимость» для конкретного запроса.

Получается, он решил, что обойти всю таблицу «дешевле», чем использовать индекс. Но почему? 🤔

Чтобы понять это, надо заглянуть в статистику объектов — таблицы и индекса.

🔍 Clustering Factor

Это один из ключевых параметров индекса. Он показывает, насколько упорядочены данные в таблице относительно порядка в индексе (в индексе они всегда отсортированы).

Как его интерпретировать?

📦 Листовые блоки индекса содержат ключи и rowid соответствующих строк.
Если при чтении индекса каждый новый rowid будет указывать на другой блок таблицы — значит, данные не упорядочены.

📈 Clustering Factor в таком случае будет большим — а это сигнал для оптимизатора, что доступ по индексу приведёт к хаотичному чтению блоков.

🧠 Почему это может быть неэффективно?

Oracle работает с блоками данных, а не с отдельными строками.

И если даже небольшой процент строк попадает под условие запроса, но все они разбросаны по разным блокам, то:
🔹 Нужно будет читать почти все блоки таблицы,
🔹 Плюс часть блоков самого индекса,
🔹 И в сумме Index Range Scan может оказаться «дороже», чем простое Table Access Full.

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

Хочешь научиться разбираться в таких нюансах сам?
👉 Записывайся на 7 поток по оптимизации: Анкета. 📋
Обсудить нюансы использования индексов и оптимизации в Oracle - велком в Чатик 💬

С вами был Костя Андронов. Всем отличного дня и приятного просмотра! 🚀

#oracle #оптимизация #index #sql #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
🔥153👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Как Валерия после 3-летнего перерыва вернулась в IT и стала увереннее, чем раньше

🔹33 года. Десять лет опыта. Но три года в декрете — и всё будто стерлось.
🔹PL/SQL, триггеры, API, запросы — всё знакомо и в то же время чужое.
🔹Ощущение, что за это время мир убежал вперёд, а ты застрял в прошлом.

Но потом Валерия решилась пойти на курс, чтобы не просто “вспомнить синтаксис”, а вернуть уверенность. И спустя пару месяцев — снова пишет код, понимает, почему так, оптимизирует, спорит на равных с коллегами и снова чувствует себя специалистом, а не человеком “после декрета”.

🔥 История Валерии — про то, как не бояться начинать заново, даже если кажется, что время ушло. Про то, как системное обучение возвращает не только знания, но и уверенность.

👉🏻 Прочитайте полную историю здесь

#oracle #оптимизация #index #sql #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
👍85🆒2
This media is not supported in your browser
VIEW IN TELEGRAM
Parallel DML на таблице с триггером

Друзья, всем привет! 👋
С вами Костя Андронов.

Продолжаем серию обсуждений интересных кейсов с практик последнего потока курса «Оптимизация Oracle SQL»

В DWH-среде для ускорения тяжёлых запросов часто применяется параллельный SQL

Например, если нам нужно вставить данные из таблицы client_data в client_data_tst, то и чтение, и вставка могут выполняться в нескольких параллельных сессиях.

Но есть нюанс ⚠️
Если на целевой таблице (client_data_tst) есть триггер, Oracle автоматически отключает PDML (параллельные DML-операции) для этой таблицы.

👉 И что же тогда делать, если хочется вставлять быстро, но триггер мешает параллелизму?

Варианты, конечно, есть — один из них разберём уже в четверг на практике 🎓
А пока — кидайте свои идеи и гипотезы в чатик 💬

Всем продуктивной недели и быстрых загрузок! 💪🚀

#oracle #оптимизация #sql #performance #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
👍8🔥43
This media is not supported in your browser
VIEW IN TELEGRAM
PDML на таблице с триггером. Ответ

Друзья, всем привет! 👋
С вами Костя Андронов.

В понедельник мы задали вопрос: как ускорить вставку данных в таблицу с триггером?

Почему Oracle отключает PDML на таблице с триггером?

Триггер может делать что угодно:
🔹 обновлять другие таблицы,
🔹 вызывать процедуры,
🔹 бросать исключения и т.д.

А при параллельном выполнении это создаёт риски:
🔸 сложно обеспечить транзакционную целостность,
🔸 легко попасть в коллизии,
🔸 поведение становится непредсказуемым.

Поэтому Oracle просто отключает параллелизм на уровне SQL — чтобы не рисковать.

Но это не означает, что мы не можем выполнять вставку параллельно вовсе. Просто управлять этим процессом теперь должен не оптимизатор, а мы сами — со стороны приложения.

🧩 Как вручную распараллелить вставку?

Один из удобных способов — использовать пакет DBMS_PARALLEL_EXECUTE.

Он позволяет легко распараллелить выполнение задачи через фоновые джобы. Что нужно сделать:

1️⃣ Создать задачу:
dbms_parallel_execute.create_task(...)


2️⃣ Разбить данные на чанки соответствующим методом:
🔹по ROWID,
🔹по колонке с типом NUMBER,
🔹или произвольным запросом с двумя колонками start_id и end_id (оба типа NUMBER).

3️⃣ Запустить выполнение:
Oracle сам создаст нужное число джобов, и будет передавать в каждый start_id и end_id через bind-переменные. Количество одновременно работающих джобов настраивается параметром при запуске.

📌 Таким образом, мы контролируем параллелизм вручную, и даже наличие триггера не мешает нам ускорить вставку.

🎥 Как это выглядит вживую — видео к посту.
💬 Обсудить решение или предложить свой способ можно в нашем Чатике
📋 А чтобы глубже погрузиться в оптимизацию — открыта предзапись на 7 поток

С вами был Костя Андронов. Всем отличного дня и приятного просмотра! 🚀

#oracle #оптимизация #sql #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"
👍143🔥2
Media is too big
VIEW IN TELEGRAM
Чтение плана запроса на собеседовании в Спортмастер 🏋️‍♂️

Друзья, всем привет!
С вами Денис 🙏🏻

Сегодня разберём реальное задание с собеседования в компанию «Спортмастер», где нужно было прочитать и объяснить план выполнения SQL-запроса.
Такие кейсы встречаются на интервью в крупных компаниях, поэтому стоит быть к ним готовым 😉

Немного контекста
Я проходил это собеседование прошлой осенью, собирая материал для курса по оптимизации.
Интересный момент — интервью проводила девушка, с которой мы вместе работали в «Магните» в 2016–2018 годах 😅
К счастью, она меня не узнала, и разговор получился очень техническим — без «поблажек по старой памяти».

Теперь к сути
Мне показали фрагмент explain plan и просили объяснить - какие операции в запросы выполняются, что они означают, какие структуры данных использовались.

Понимание плана выполнения — это навык, который проверяют не только в «Спортмастере», но и в банках, телекомах и крупных e-commerce.

Если при виде execution plan вы чувствуете неуверенность — самое время подтянуть знания.
Такие задания часто определяют, пройдёте ли вы техническое интервью или «застрянете» на объяснении простого Full Scan.

🎥 На youtube в HD-качестве

А если хотите научиться читать планы запросов любого уровня сложности - вы знаете что делать 😉

#Oracle #SQL #оптимизация #executionplan #интервью #спортмастер #Denis_Kivilev

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"

📱 Facebook 📱 YouTube 📱 ВКонтакте 📱 LinkedIn 📱 Threads RUTUBE
Please open Telegram to view this post
VIEW IN TELEGRAM
👍30🔥102🤝2🤩1
Dbms_rowid интересный пакет, который может пригодится

Друзья, всем привет! 👋
С вами Денис.
В нашем канале разного уровня специалисты, этот пост зайдет Middle- и Senior-ребятам, но и Junior могут почерпнуть полезное.

Итак, каждый разработчик Oracle хотя бы раз сталкивался с ROWID — уникальным идентификатором строки в базе. Cодержит информацию о типе ROWID, идентификаторе объекта, относительном номере файла (relative file number), номере блока и номере строки в блоке.

Но как разобрать его на части или создать искусственно? Здесь на помощь приходит пакет DBMS_ROWID. Это не просто утилита, а мощный инструмент для глубокого анализа и манипуляций с данными на уровне блоков. В реальной жизни он спасает при отладке, миграциях или оптимизации хранения. Без него сложно понять, где именно лежит ваша запись в файлах данных.

Пакет DBMS_ROWID появился в Oracle для работы с ROWID из PL/SQL и SQL. Он позволяет извлекать информацию о блоках данных, файлах, объектах и даже создавать тестовые ROWID.

Ключевые функции пакета

DBMS_ROWID.ROWID_CREATE — создает ROWID для тестирования. Полезно, когда нужно симулировать запись без реальной БД.
DECLARE
v_rowid ROWID;
BEGIN
v_rowid := DBMS_ROWID.ROWID_CREATE(
rowid_type => sys.dbms_rowid.rowid_type_extended,
object_number => 12345,
relative_fno => 1,
block_number => 100,
row_number => 5
);
DBMS_OUTPUT.PUT_LINE(v_rowid);
END;


DBMS_ROWID.ROWID_INFO — разбирает существующий ROWID на компоненты: тип, номер объекта, файл, блок и строку.
DECLARE
v_rowid ROWID := 'AAAAAAAABAAAALaAAA';
v_type NUMBER;
v_object NUMBER;
v_file NUMBER;
v_block NUMBER;
v_row NUMBER;
BEGIN
DBMS_ROWID.ROWID_INFO(
rowid_in => v_rowid,
rowid_type => v_type,
object_number => v_object,
relative_fno => v_file,
block_number => v_block,
row_number => v_row
);
DBMS_OUTPUT.PUT_LINE('Объект: ' || v_object || ', Блок: ' || v_block);
END;


Другие полезные модули
ROWID_BLOCK_NUMBER возвращает номер блока,
ROWID_OBJECT — номер объекта,
ROWID_RELATIVE_FNO — относительный номер файла,
ROWID_ROW_NUMBER — номер строки в блоке,
ROWID_TO_ABSOLUTE_FNO — абсолютный номер файла,
ROWID_TO_EXTENDED и ROWID_TO_RESTRICTED для конвертации типов,
ROWID_TYPE для проверки типа,
ROWID_VERIFY для валидации.

Для чего использовать DBMS_ROWID
🔸 Диагностика инцидентов — быстро найти физическое местоположение проблемной строки по ROWID из alert.log/trace.
🔸 Анализ ошибок — определить повреждённый блок, файл и объект.
🔸 Контроль миграций/восстановлений — сверка фактического физического размещения строк между средами.
🔸 Анализ распределения данных — понять плотность блоков, выявить горячие сегменты или неэффективную кластеризацию.
🔸 Работа с партиционированием — определить точный партишен/subpartition, где находится строка.
🔸 Точечный доступ к данным — выборка строк по известным физическим координатам без сложных JOIN.
🔸 Служебное логирование — фиксировать ROWID проблемных записей для последующей диагностики.
🔸 Создание воспроизводимых тестов — моделирование ситуаций с повреждёнными или смещёнными строками.

Пост был навеян лекцией в субботу. Показывал ребятам свой код с Магнита, написанный в 17м году. И наткнулся на dbms_rowid.rowid_object(v_rowid). На скрине выше ⬆️


Используете ли вы DBMS_ROWID в проектах? Поделитесь кейсами, когда он выручил, в комментариях 💬

Всем продуктивного дня и удачных запросов! 🌟

#oracle #dbms_rowid #rowid #plsql #oracledev #базыданных #sql

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL"

📱 Facebook 📱 YouTube 📱 ВКонтакте 📱 LinkedIn 📱 Threads RUTUBE
Please open Telegram to view this post
VIEW IN TELEGRAM
👍131
NVL, COALESCE и NVL2: различия и практические кейсы

Друзья, всем привет! 👋

Сегодня разберём три функции для работы с NULL, которые часто путают начинающие разработчики: NVL, NVL2 и COALESCE.

На первый взгляд все они решают одну задачу — заменяют NULL на что-то осмысленное. Но каждая имеет свои особенности, которые влияют на производительность и результат выполнения запроса.

NVL (Null Value Logic)

Самая простая и древняя функция Oracle для замены NULL.

Синтаксис:
NVL(выражение, значение_если_NULL)


🔹 Принимает ровно 2 аргумента
🔹 Если первый аргумент NULL — возвращает второй
🔹 Вычисляет оба аргумента (кроме констант - Oracle их оптимизирует)

Пример:
SELECT employee_name, NVL(commission_pct, 0) AS commission
FROM employees;


COALESCE (Стандарт SQL)

Более гибкая функция, которая может принимать любое количество аргументов.

Синтаксис:
COALESCE(выражение1, выражение2, ..., выражениеN)


🔹 Принимает 2 и более аргументов
🔹 Возвращает первое найденное не-NULL значение из списка
🔹 Вычисляет аргументы последовательно и останавливается на первом не-NULL (более эффективно!)

Пример:
SELECT employee_name,
COALESCE(mobile_phone, work_phone, home_phone, 'No phone') AS contact
FROM employees;


NVL2 (расширенная версия NVL)

Уникальная функция Oracle для разных значений в NULL и не-NULL случаях.

Синтаксис:
NVL2(выражение, значение_если_НЕ_NULL, значение_если_NULL)


🔹 Принимает ровно 3 аргумента
🔹 Если первый аргумент НЕ NULL — возвращает второй
🔹 Если первый аргумент NULL — возвращает третий

Пример:
SELECT employee_name,
NVL2(commission_pct,
salary + (salary * commission_pct),
salary) AS total_compensation
FROM employees;


Практический кейс: производительность

Важный момент! NVL всегда вычисляет оба аргумента (кроме констант), а COALESCE — только до первого не-NULL.

-- NVL вызовет expensive_function() ВСЕГДА
SELECT NVL(column_value, expensive_function()) FROM table_name;

-- COALESCE вызовет только если column_value IS NULL
SELECT COALESCE(column_value, expensive_function()) FROM table_name;


Если у вас миллионы строк и дорогая функция — разница будет колоссальной! 🚀

Практический кейс: множественные проверки

Найти первый доступный контакт клиента:

-- С NVL — громоздко
SELECT NVL(NVL(NVL(email, mobile), work_phone), 'No contact')
FROM customers;

-- С COALESCE — элегантно
SELECT COALESCE(email, mobile, work_phone, 'No contact')
FROM customers;


Практический кейс: условная логика с NVL2

Расчёт бонуса по разным формулам:

-- Без NVL2 — через CASE
SELECT employee_name,
CASE WHEN commission_pct IS NOT NULL
THEN salary * 0.1
ELSE salary * 0.05
END AS bonus
FROM employees;

-- С NVL2 — компактнее
SELECT employee_name,
NVL2(commission_pct, salary * 0.1, salary * 0.05) AS bonus
FROM employees;


Ловушка с типами данных

-- Ошибка! Несовместимые типы
SELECT NVL(salary, 'Unknown') FROM employees;

-- Правильно — приводим к одному типу
SELECT NVL(TO_CHAR(salary), 'Unknown') FROM employees;

-- Oracle обрабатывает пустую строку как NULL!
SELECT NVL('', 'Default') FROM dual; -- Вернет 'Default'


Обратите внимание: NVL всегда возвращает тип первого аргумента, а COALESCE — может выбрать более общий тип (например, NUMBER + VARCHAR2 даст VARCHAR2).

Когда что использовать?

NVL — для простой замены NULL на значение по умолчанию (Oracle)

COALESCE — когда нужно проверить несколько значений или важна производительность (современный подход!). Стандарт SQL — работает везде!

NVL2 — когда нужна условная логика на основе NULL/не-NULL (Oracle)

Вывод

Все три функции решают проблему NULL, но по-разному:
• NVL — простая, но ограниченная
• COALESCE — гибкая и эффективная
• NVL2 — для условных сценариев

Какую функцию вы используете чаще? Делитесь опытом в чате! 💬

Всем продуктивной разработки и минимум NULL-проблем! 🚀

#oracle #nvl #coalesce #nvl2 #sql #null #базыданных #разработка #plsql

Канал Oracle Developer | Чатик 💬
Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL" 🔥

📱 Facebook 📱 YouTube 📱 ВКонтакте 📱 LinkedIn 📱 Threads RUTUBE
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2010