Все о разработке в СУБД "Oracle" SQL, PL/SQL, оптимизация, архитектура, сертификации и многое другое.
select * from tab1 where id = 1; select * from tab1 where id = 2;Для каждого будет сгенерирован свой sql_id, свой план(возможно), будут помещены в кэш-запросов и т.п. множество накладных расходов. 4️⃣ Для решения подобной ситуации используются переменные связывания (bind vars). Вместо жестко заданного литерала (1, 2…) используется подстановка значения:
select * from tab1 where id = :var;теперь в var можно подставлять значения 1, 2…и т.д. Не будет hard parse при подстановке значений. Не забивается кэш-запросов, DBA довольны. Том Кайт в своей книге “Oracle для профессионалов” буквально на первых же страницах пишет про связные переменные. Это было теоретическое введение. Перейдем к нашему примеру. Некое приложение соединяющееся c БД под пользователем ONE_C выполняло однотипный запрос аж 11166 раз (см. скриншоты ⬆️). Текст запросов отличается ровно в одной детали - использование разных ID в предикате (where t1…. = число). Да, из задания это не совсем очевидно. Поскольку в текстовом виде это абсолютно разные запросы, бедная СУБД выполнила аж 11166 раза hard pars забив кэш-запросов. Решение простое. Использовать переменную связывания в предикате, в которую подставлять конкретное значение.
select ... where t1… = :idбудет выполнен 1 раз hard parse и всё. ⚠️ Не надо нагружать СУБД бесполезной никому не нужной нагрузкой К сожалению, в рассматриваемой БД таких запросов не мало. Нужно явно править приложение 🛠 Этим грешат начинающие DBD, разработчики, пишущие на других языках, выполняющие запросы к СУБД Oracle. Уровень задачи легкий, т.к. это должен знать каждый кто использует СУБД Oracle. Это основы. На курсе по оптимизации будем разбирать множество интересных кейсов 😉 Обсудить в чатике #оптимизация #решениезадачи
select parsing_schema_name
,substr(t.sql_text, 1, 100)
,count(*) cnt
from v$sqlarea t
group by t.parsing_schema_name, substr(t.sql_text, 1, 100)
order by cnt desc;
Результаты на скриншоте.
Какие выводы можно сделать по результатам выполнения? Все ли нормально? Если да, то почему? Если нет, то, какие есть предположения по устранению проблем?
Уровень сложности: easy, самые основы.
Объяснение, как всегда, в четверг 🎓
Обсудить в чатике
#задачаselect chr(ascii('A') + level - 1)
from dual
connect by level <= ascii('Z') - ascii('A') + 1;
Всем неравнодушным респект, было интересно посмотреть на такое разнообразие 🔥
#решениезадачиselect c.id
,c.name
,max(a.city || ', ' || a.street || ', ' || a.house || ' fl. ' || a.flat)
keep(dense_rank first order by a.a_type desc, nvl2(a.city, 1, 0)
+ nvl2(a.street, 1, 0) + nvl2(a.house, 1, 0) + nvl2(a.flat, 1, 0) desc, a.created desc) address
,max(ph.c_info) keep(dense_rank first order by ph.created desc) phone
,max(em.c_info) keep(dense_rank first order by em.created asc) email
from client c
left join address a on a.client_id = c.id and a.active = 'Y'
left join contact ph on ph.client_id = c.id and ph.c_type = 1 and ph.active = 'Y'
left join contact em on em.client_id = c.id and em.c_type = 2 and em.active = 'Y'
group by c.id, c.name;
Пояснения
Решение основано на аналитических функциях.
1️⃣ Основная сущность клиент. Соединяем с ним все дочерние.
2️⃣ В условиях соединения указываем “Y” - активность.
3️⃣ Таблицу contact соединяем дважды с разными типами контактов “1” и “2”.
4️⃣ Группируем по клиенту - фактически c.id, c.name это группировка до одного уникального клиента, просто для вывода имени.
5️⃣ Для получения требуемых данных применяем аналитическую функцию keep dense rank в режиме агрегации (group by указан).
6️⃣ Для получения адреса:
- группировка по клиенту у нас уже есть, т.е. мы работаем уже внутри партиции “одного клиента”.
- сортируем строки внутри партиции по типу (a.a_type desc), по заполненности из перечня атрибутов (сумма nvl2) и дате создания (a.created desc).
- берем первую запись first из отсортированной партиции.
max(a.city ', ' a.street ', ' a.house ' fl. ' a.flat) - говорит просто отдай MAX запись из отобранных (а это у нас только одна). Фактически она ни на что не влияет.
7️⃣ Для получения телефона применяется аналогичная конструкция как и для адреса с более простой сортировкой.
8️⃣ Для получения email применяется аналогичная конструкция как и для адреса с более простой сортировкой.
Если не хотите ломать глаза ➡️ в более читаемом виде.
Спасибо, всем кто публиковал свои решения в нашем чатике 👍
#решениезадачи #аналитическиефункции