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

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

Отец-основатель: @denis_dbd Кивилёв Денис
Download Telegram
Конечно, на собеседовании, от вас хотят услышать про последние два пункта.
В реальной жизни, нельзя исключать другие.

В следующем посте, расскажу про то как исследовать проблемы в сессии с точки зрения планов выполнения запросов.

#теория #оптимизация
Задача: дана табличка, в ней четыре строки, столбец “n”.
Значения в столбце: 1, 2, 3, 4.
Дан запрос. Каков будет результат его выполнения (как будут заполнены ячейки).

Запрос:
select n,
sum(n) over () sum1,
sum(n) over (order by n) sum2,
sum(n) over (partition by n) sum3
from demo;

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

Смотрите объяснение в посте в четверг 🎓

#sql #задача
DML без прерывания выполнения при возникновении ошибок (log errors)

Всем привет!
Запилил новый видос, за который вы когда-то проголосовали.
В нем, я расскажу как выполнять DML-операции в которых могут возникнуть ошибки, при этом не прерывая выполнение всей операции.

Представьте вам нужно вставить 100 записей, 10 из них могут вызвать ошибку. При этом нужно, чтобы вставка остальных 90 записей прошла успешно. Для этого используется расширение команд DML => log errors.

Видео будет небольшое, но информативное.

Приятного просмотра!

🎥 Смотреть видео - 5 мин

#видео #dml #logerrors
Задача: что будет в результатах выполнения запроса. Полную постановку смотрите в посте вторника.

Решение:
Эта задача на знание аналитических функций. Тема не простая. Требует знаний и, самое главное, практики. В формате постов на канале такое не объяснить. Эта тема будет рассматриваться в моих обучающих курсах.

Итак:
1) sum1 - это итоговая сумма по всем значениям колонки n. Т.е. в каждой ячейке будет: 10 (1+2+3+4).
2) sum2 - это нарастающий итог. Значение текущей ячейки суммируется с суммой в предыдущей ячейки. Например: для n = 1, это будет 0+1, для n = 2 => 1 + 2, для n = 3 => 3 + 3. Есть особенности, если n - одинаковые.
3) sum3 - инструкция partition by разбивает нашу таблицу на условные партиции и в них считает сумму. Поскольку у нас повторяющихся n нет, то сумма будет равна n.

Если вы не поняли, рекомендую воссоздать пример и поиграться. Понимание аналитических функций важный шаг на пути разработчика.

#sql #решениезадачи #аналитическиефункции
Поиск проблем в сессии

Продолжаем про проблемы с производительностью.
Допустим мы выяснили, что никто ничего не менял, никаких работ с СУБД не было. Все работает в штатном режиме. Раньше пользователь жмакал условную “кнопку” и функционал отрабатывал 1 секунду. В один прекрасный момент, время увеличилось до минуты. Пользователя это не устраивает.

Сейчас не рассматриваем средний слой, сеть и прочее, предположим, что это вообще не менялось и не вносит никаких “тормозов”. Соответственно, остается только слой БД. Кстати, приложение обвешанное метриками, сузит область поиска.

Итак, начать стоит с разбора конкретной сессии, которая кроется за функционалом этой “кнопки”. Функционал - это PL/SQL + SQL.

Обычно, идут по пути наименьшего сопротивления, и исследуют на предмет тормозов SQL, если же ничего криминального в запросах не обнаруживается, берутся за PL/SQL.

В следующих постах, я немного раскрою тему про исследование SQL-запросов.

#теория #оптимизация
Какие запросы выполняются в сессии

Есть несколько способов получить информацию по запросам в БД.

1) AWR-отчет - это срез самочувствия БД за определенный период. В нем очень много разной информации. Нас как разработчиков заинтересует раздел с TOP-сессиями в БД в различных разрезах. AWR-отчет это как средняя температура по больнице. В нем видна работа вообще всех сессий, нас же интересует конкретная. Тем не менее, при удаленной диагностики (БД не на вашей площадке), вполне подойдет, чтобы понять картину происходящего в целом.

2) Трейс-файл - специальный файл, который снимается с начала до конца работы конкретного функционала. Соответственно, в него попадут только те запросы, которые выполняла наша сессия. В нем будут реальные планы запросов, ожидания, другая информация.
Также, будет крайне полезен, при удаленной диагностики.
3) Представления v$* и dba_* - системные представления, которые показывают выполняющиеся сессии (планы, ожидания и т.п.) в данный момент + есть возможность посмотреть историю. Яркими представителями являются v$active_session_history и dba_hist_active_sess_history.
Подходит, когда доступ к БД у вас есть. Нет необходимости снимать трейс-файл, достаточно будет посмотреть в эти view.

#теория #оптимизация
Задача: обойти таблицу с использованием иерархического запроса, начиная с вершины (строка у которой нет потомков). В запросе вывести уровень иерархии, поля name, year текущего уровня и поля name, year родителя.

Структура таблицы:
create table example
(
name varchar2(200 char) not null,
year number(4) not null,
p_name varchar2(200 char),
p_year number(4)
-- еще столбцы
);

alter table example add constraint example_pk primary key (name, year);
alter table example add constraint example_fk foreign key (p_name, p_year)
references example (name, year);

Смотрите объяснения в посте в четверг 🎓

#sql #задача
You asked…
У меня есть Master-таблица с автогенерируемым PK. Я создал процедуру, в которой делаю INSERT в мастер таблицу, получаю в ней сгенерированный ID (PK).
Далее использую его для вставки в child-таблицы.
Таких таблиц у меня много.

1) Является ли это хорошей практикой, использовать процедуры для выполнения вставки?
2) Нужно ли создавать для каждой таблицы обертку в виде процедуры?

...and we said
Если кратко. То это хороший принцип построения архитектуры. В статье Тома, есть ссылка на другую статью "SmartDb\ThickDB" раскрывающую принцип модульности, интерфейсов, сокрытия реализации. Рекомендую изучить.

Подробности в статье Тома.

От себя добавлю. В наших проектах, мы стараемся делать низкоуровневые API для работы с физическими объектами. Бизнес-логика при этом реализуется на среднем слое.
Конечно, не в каждом проекте это применимо. Например, кто-то использует ORM для работы с БД.

#asktom #архитектура
Задача: постановку смотрите в посте вторника.

Решение:
select level
,t.name
,t.year
,prior name parent_name
,prior year parent_year
from example t
connect by prior t.name = t.p_name
and prior t.year = t.p_year
start with t.p_name is null and t.p_year is null;


* level - уровень иерархии.
* name, year - поля текущего уровня иерархии.
* prior - через конструкцию prior можно обращаться к полям родителя.
* соединение предка с потомком:
в соединении участвуют два поля name/year, соответственно, надо через AND перечислить оба поля.
* start with - нужен для указания с какого узла мы разворачиваем нашу иерархию. В данном случае, стартуем с узлов, у которых нет предков.

Может смутить наличие двух полей, участвующих в иерархии. Именно в таком виде, мне встречалась задача на собеседовании.

#sql #решениезадачи #иерархическиезапросы
Всем привет!
Отпуск закончился 🌴
Я с новыми силами берусь за любимое дело.
Итак, поехали 😉
План запроса - это то, как СУБД будет выполнять наш запрос.
А именно:
1. Какие структуры хранения будет использовать;
2. Как будет извлекать из них данные;
3. Как будет соединять таблицы;
4. Как будет сканировать партиции;
5. Как будет выполнять другие необходимые действия.

sql_id - это уникальный идентификатор SQL-запроса.
plan_hash_value - это уникальный идентификатор плана SQL-запроса.
У одного запроса может быть несколько планов выполнения.

Планы запросов формирует стоимостной оптимизатор. За основу берется хранящаяся статистика по объектам, участвующих в запросе. А также подсказки разработчика (hints, хинты).

Статистика - это регулярно собирающаяся информация по объектам БД. Например: количество строк, количество уникальных значений, глубина индексного дерева и прочие характеристики.

Как читать план запроса?
Обсудим в одном из следующих постов.

#теория #оптимизация
Задача: имеется таблица. Заполнена данными. Выполняется запрос. План запроса показан на рисунке.
Что в этом запросе некорректно, на какие мысли наталкивает план выполнения, как можно исправить?

Скрипты:
create table my_order(
order_id number,
sernum varchar2(100 char),
order_date date
)
partition by range (order_date)
interval (interval '1' month)
(
partition pmin values less than (date '2008-01-01')
)
enable row movement;

alter table my_order add constraint my_order_pk
primary key (order_id, order_date) using index local;

insert into my_order
select level, level, sysdate - level
from dual connect by level <= 1000;
commit;

select * from my_order t where t.order_id = :x;

Смотрите объяснения в посте в четверг 🎓

#sql #задача
план запроса
You asked…

У меня вопрос по поводу Varray (это один из типов коллекций в Oracle).
Зачем именно они нам нужны? Можете ли вы привести пример их использования?
Было бы интересно узнать ваше мнение.

...and we said

Я никогда их не использую. Я использую nested tables в PL/SQL-коде.
Также, никогда не использую коллекции в качестве столбцов физических таблиц.
Varray лимитированы размером и их не очень удобно использовать в коде.

Подробности в статье Тома

⚠️ От себя добавлю. В реальной жизни, кроме как на собеседованиях тип Varray мне не встречался. Использовать в качестве типа столбца таблицы - является плохим тоном по разным причинам. В PL/SQL-коде nested tables хватает более чем.

#asktom #коллекции #varray
Задача: смотрите постановку в посте вторника.

Решение:
Довольно частая ошибка ДБД. Таблица секционированная, однако ключ секционирования в запросе не использован. СУБД вынуждена сканировать все партиции. Чем больше у нас партиций, тем больше трудоемкость этой операции.

В плане такие кейсы обнаружить достаточно просто. Стоит обратить внимание на столбцы:
Pstart - с какой партиции начинается сканирование.
Pstop - какой партицией заканчивается.

В нашем исходном плане, Pstart = 1, Pstop = 1048575 (условный максимум).
Т.е. сканирование начинается с первой партиции и заканчивается самой последней.
Partition Range All - также, непрозрачно намекает на сканирование всех партиций.

Наша задача не забыть добавить ключ секционирования в запрос. Где это значение взять? Уже другой вопрос. Существуют различные методики. Может быть, как-нибудь напишу.

Pstart - должен начинается точно не со значения 1. Это может быть KEY(AP) или номер одной из последних секций. Зависит от того как вычисляется стартовая\конечная секции.

#решениезадачи #секционирование
План запроса с добавлением ключа секционирования.

* Pstart = KEY
* Pstop = 1048575
* Partition Range Iterator.

#sql #решениезадачи #оптимизация #секционирование
Отвлечемся на время от оптимизации.

Глобальные временные таблицы (GTT) - таблицы, используемые для хранения данных на время транзакции или сеанса.

Память для хранения данных выделяется во временном ТП (TEMP). При манипуляции с этими данными генерируется крайне мало redo-информации.

Очень часто происходит путаница по срокам жизни таблицы и данных.
GTT - создаются заранее, а не по ходу выполнения приложения. Их не нужно создавать в каждой сессии. А нужно лишь заполнять данными. Данные между сессиями не видны.

Существует два типа GTT:
1) Хранят данные до commit’a (on commit delete rows)
2) Хранят данные до окончания сеанса (on commit preserve rows).

Тип можно задать только при создании.

Синтаксис:
create global temporary table name_gtt 
(

)
on commit delete rows;

или

create global temporary table name_gtt 
(

)
on commit preserve rows;

Есть ограничения по использованию, но на практике это никогда не мешает. О практическом использовании напишу в следующем посте.

#временныетаблицы
Задача: Есть таблица my_table. На момент вставки она пустая. Что выведет select?

Структура таблицы:
create global temporary table my_table
(
id number(30) not null
)
on commit delete rows;

Скрипт:
insert into my_table values(1);
insert into my_table values(2);

grant select on my_table to some_user;

select count(*) from my_table;


Смотрите объяснения в посте в четверг 🎓

#sql #задача