Сегодня понедельник — самое время для технической задачки 🔥
Один из наших подписчиков прислал интересный кейс, и мы решили им поделиться с вами.
Итак, ситуация:
На проекте по импортозамещению выполнили миграцию с одной из западных CRM-систем на продукт собственной разработки. В качестве СУБД используется Oracle 19c (Standard Edition).
Во время переноса:
🔶 для истории действий пользователей была создана таблица user_logs. 🔶 Объём — 3 миллиарда строк 🔥 🔶 По требованиям законодательства данные должны храниться не менее 5 лет. 🔶 Таблица НЕ секционирована (ограничения редакции SE).
Периодически нужно получать все события (event_type) по клиенту (client_id) за последние N дней.
Пример запроса:
SELECT event_type, event_date, description FROM user_logs WHERE client_id = :client_id AND event_date >= SYSDATE - 90 ORDER BY event_date DESC;
❗️Проблемка:
🔶 Запрос к одному клиенту выполняется 20–30 секунд. 🔶 Если клиент активный (около 100 000 событий за 3 месяца) — всё становится совсем грустно 🐌 - В плане видно Index Range Scan по индексу (client_id, event_date), но нагрузки на I/O всё равно большие 🤷♂️
Условия:
1️⃣Materialized View не вариант — нет места под дублирование данных. 2️⃣ Переехать на Enterprise Edition в ближайшие месяцы нет возможности🤷♂️
Вопрос: как ускорить выполнение запроса без секционирования❓
Кто решит — плюсик в карму и +100 к уважению в нашем чате Oracle-разработчиков 🚀
Пока мы готовим серию постов про сортировку, предлагаем поразмять мозги над одной из задачек.
Перед вами план запроса, который создаёт таблицу с архивными данными продаж старше двух последних недель. На основании этого плана нужно понять, как ускорить запрос, не меняя при этом его текст.
Версия Oracle: 12.2.0.1 Структура индекса из 4 операции: SALE_DT, COSTUMER_ID, RETAILER_ID.
Predicate Information (identified by operation id): ---------------------------------------------------
4 - access("S"."SALE_DT"<=TRUNC(SYSDATE@!)-14)
Пишите в комментариях свои вопросы, идеи, предложения 👇🏻
Мы продолжаем делиться с вами важными новостями из жизни нашей онлайн-школы! 📚
В январе мы писали пост о получении лицензии Минобразования. Но решили на этом не останавливаться! 😉
Денис и Павел прошли профессиональную переподготовку и получили квалификацию «педагог дополнительного образования»! 🎓🎉
Да-да, теперь мы не только крутые практики с многолетним опытом в разработке, но и дипломированные преподаватели! 🔥 И это не просто «красивая бумажка» — это подтверждение того, что мы умеем и можем обучать на уровне, соответствующем государственным стандартам. 💪
Каждый из нас пришёл в преподавание своей дорогой: 🔶 Денису предложили провести внутреннее обучение в QIWI, где он тогда работал 💼 🔶 Павел ещё в университете больше прислушивался к предпринимателям, которые иногда приезжали читать лекции.
Со временем мечта превратилась в хобби, которое, в свою очередь, выросло в полноценную онлайн-школу. Поэтому получение педагогического образования стало логичным шагом на пути к развитию. Ведь одно дело — объяснять «на пальцах» в узком кругу, а совсем другое — выступать перед широкой аудиторией и подавать материал так, чтобы «понял даже лабрадор», как любит говорить Денис. 😉
Что это даёт онлайн-школе❓
🔸 Более качественные и гибкие программы с учётом методических стандартов 🔸 Прозрачность и легитимность — особенно важно для корпоративного обучения 🔸 Авторитет. У кого вы предпочтёте учиться: — у человека, который «и швец, и жнец, и один в поле воин», — или у команды, которая постоянно развивается, получает дополнительное образование и привлекает таких же энергичных, объединённых общей идеей инженеров?
А что это даёт вам — нашим студентам❓
✅ Уверенность в том, что вы учитесь у тех, кто знает не только «как работает», но и как объяснить «так, чтобы дошло». ✅ Эффективные обучающие программы: никакой воды, только то, что действительно помогает развиваться. ✅ Индивидуальный подход: мы знаем, что все студенты индивидуальны, поэтому адаптируем стиль и содержание уроков под ваши способности и потребности. 🎯
Что же дальше❓
Дальше — ещё интереснее! 🤟🏻
Мы уже работаем над запуском новых курсов, где обязательно применим наши новые знания и навыки. А ещё усиливаем команду и продолжаем делать качественный контент, чтобы вам было ещё легче и увлекательнее учиться. 🌟
В понедельник мы выкладывали техническую задачу по оптимизации. Скажу по секрету, такие задачи задают на собеседовании в одном из крупных ритейлеров.
Итак, если посмотреть на план запроса, видно, что узкое место в том, что мы выгребаем из индекса 4 млн. записей, хотя архивная копия по размеру будет очень близка к исходной таблице (разница всего в 2 недели).
Какие можно дать рекомендации❓
1️⃣Сбор статистики
Смотрим на статистику таблицы sales
SELECT stale_stats FROM user_tab_statistics WHERE table_name = 'SALES'
Если запрос вернет YES или <NULL> - статистика неактуальна, делаем
Если статистика актуальна, а оптимизатор все равно считает, что нужен индекс, следует выполнить ALTER INDEX SALES_IDX INVISIBLE.
3️⃣SQL Plan Management
Минус подхода с SQL Plan Management в том, что если вендор доработает запрос, наша «магия» с подменой плана исчезнет :( Но часто он помогает устранить "острую боль", когда нет возможности оперативно выпустить патч или исправить тормозящий запрос. Про этот подход мы более подробно рассказываем на нашем курсе по оптимизации. Там же есть куча вопросов с собеседований и тестовых заданий. Так что если вы хотите к ним лучше подготовиться - welcome
Ставь лайк, если ответил верно. Делитесь в комментариях, у кого еще Index Range Scan тормозил прод.
Сегодня понедельник, самое время немного взбодриться после длинных выходных ☕️ И для разогрева предлагаем вопрос, который любят задавать на технических собесах: что же лучше — IN или EXISTS?🤔
Итак, перед вами два запроса. Вроде бы делают одно и то же… но есть нюанс👇
-- Not Exists SELECT /*+ FULL(d) */ d.department_name FROM hr.departments d WHERE NOT EXISTS ( SELECT 1 FROM hr.employees e WHERE e.department_id = d.department_id);
-- Not IN SELECT /*+ FULL(d) */ d.department_name FROM hr.departments d WHERE d.department_id NOT IN ( SELECT e.department_id FROM hr.employees e);
🔍 На первый взгляд — разницы нет. Но если присмотреться… 😏
💬 Напишите в комментариях к посту, в чём подвох.
И если вдруг вы не до конца понимаете, в чём отличие между IN и EXISTS, добро пожаловать на наш мини-эфир в четверг🎙
Разберём по пунктам:
🔶 Сходства и отличия IN и EXISTS🔄 🔶 Как работают SEMI JOIN и ANTI JOIN под капотом ⚙️ 🔶 Какие вопросы по этой теме любят на собеседованиях 🧠 🔶 Примеры из практики 📌
📩 Ссылку на Zoom пришлём утром в четверг — следите за новостями в канале, чтобы не пропустить!
Личный бренд Oracle-специалиста: всё начинается с тебя
Друзья, всем привет! 👋🏻
Сегодня немного не про SQL и не про оптимизацию запросов. Сегодня — про тебя и твой личный бренд🤝
Почему это важно❓
Потому что никто, кроме тебя, не сможет убедить других в твоей крутости. Но хорошая новость в том, что этот процесс управляемый 🚀
Почему одних зовут «тушить пожары» за 500К, а других — максимум на поддержку❓
Не из-за случайного везения и не из-за «связей». Просто первый уже собрал вокруг себя мощный образ:
✅реальные кейсы с продакшена ✅ умение решать нестандартные задачи ✅понятную миссию и огонь в глазах
А второй… просто «хороший парень, который умеет посмотреть explain-план запроса» 🙈
Из чего же вырастает бренд, который бьёт конкурентов❓
1️⃣ Навыки уровня решу-любую-боль
Вы не просто знаете 1001 hint, вы уже:
✅ оптимизировали отчёт с 20 мин до 15 сек; ✅ разложил 20 ТБ архива по партициям и сэкономил железо; ✅ подняли SLA, убрав ночные крон-фейлы.
2️⃣ Желание расти и быть лучшим
Ты не ждёшь указаний, ты сам ищешь вызовы. Каждый вызов — это +10% к твоей рыночной стоимости 💹
3️⃣Цель → миссия → позиционирование
Цель: работать удалённо и жить у океана 🏖️
Миссия: делать системы быстрее и надёжнее 🚀
Позиционирование: Oracle Performance Engineer, который доказывает выгоду цифрами
HR это считывает за 30 секунд🧠
4️⃣Непрерывное развитие
Прочитал про SQL Macro? Сразу проверил в тестовом стенде. Узнал про AI Vector Search? Написал pet-проект, выложил на Git. Мир видит не картинку, а динамику.
Что получаешь в итоге❓
✅ Тебя зовут “спасти проект”, а не "попробовать" ✅ Ты сам называешь цену — и обосновываешь её кейсами ✅ Пока спишь, твой LinkedIn📱 и репозитории работают на тебя 🖥
Всё начинается с одного вопроса «Кем я хочу стать через год — и чем докажу это рынку?»
Записал ответ❓
Тогда:
1️⃣ Вспоминаешь 3 самых мощных кейса 2️⃣ Описываешь: проблема → действия → цифры 3️⃣ Запускаешь рубрику «Performance Friday» в своём блоге 4️⃣ Каждые 2 недели добавляешь новую историю в портфолио
И уже через полгода у тебя будет бренд, мимо которого не пройдёт ни один рекрутер💼
Хочешь быстрее и системно❓
На нашем летнем потоке мы:
🔶 собираем твои “сырые” навыки в кейсы 🧱 🔶 настраиваем позиционирование и резюме 🔶 шлифуем 📱, чтобы HR влюбился с первого скролла 🔶 тренируемся проходить собесы с харизмой на максимум 💪
🎯 У нас это уже сработало — а значит, сработает и у тебя.
💬 А теперь — вопрос в лоб: какую задачу, достойную места в витрине твоего бренда, ты решил за последнее время?
Пиши в комментарии, вдохновляй других — будем расти вместе 🙌
В понедельник мы показали вам два запроса и спросили, чем они отличаются.
Многие сходу ответили, что NOT IN не вернет данных, если подзапрос содержит Null-значения. И это правильный ответ ✅
Никакой магии тут на самом деле нет. Условие id IN (1,2,null) можно развернуть как: id = 1 OR id = 2 OR id = null А id NOT IN (1,2,null) — как: id != 1 AND id != 2 AND id != null
⛔️ Условие id != nullникогда не выполнится, поэтому такой запрос ничего не возвращает.
📌 К слову, такой вопрос часто задают на технических собеседованиях.
Если хочется копнуть в сторону IN и EXISTS чуть глубже — ждем вас сегодня в 19:00 МСК на обещанный вебинар🎓
Что разберем на вебинаре?
🔶 Сходства и отличия IN и EXISTS🔄 🔶 Как работают SEMI JOIN и ANTI JOIN под капотом ⚙️ 🔶 Какие вопросы по этой теме любят на собеседованиях 🧠 🔶 Примеры из практики 📌
Будет возможность задать вопросы и разобрать свои кейсы.
Кому будет полезно? 🔸 Начинающим разработчикам – чтобы не наступать на типичные грабли. 🔸 Мидлам – чтобы писать более эффективный код. 🔸 Всем, кто хочет хорошо проходить собеседования.