Друзья, всем привет!
На носу у нас новый год 🎄, а значит самое время подвести итоги:
1️⃣ Канал, наконец-то, перевалил цифру в 3000 подписчиков.
Уже давно не занимался его раскруткой, а это значит, что работает сарафанное радио 🗣
2️⃣ Было опубликовано более 100 постов.
Начали подключаться участники канала к написанию контента. Надеюсь эта тенденция сохранится ✏️
3️⃣ В чате сформировалось сообщество, которое готово прийти на помощь советом, кодом, мнением.
Спасибо, ребята!
4️⃣ Я дописал и провел первый поток по курсу "Основы оптимизации Oracle SQL".
Получился довольно качественный продукт, не похожий на аналоги.
5️⃣ И даже, провели первый конкурс 😊
Результаты, которого, пора подвести.
ТОП-3 задачки 🏆
1 место (5К) - сбор мусора Михалычем
2 место (3К) - создание deadlock
3 место (2К) - вывод календаря
отдельный приз (2К) - самый популярный ответ в чате. их было два.
Новогодние подарки победителям уже отправлены 🎁 🎈
Всем спасибо за участие, в следующем году повторим 👍
~~~~
Кстати, это уже четвертый (!) новый год, с которым я поздравляю вас в нашем канале 🥳
От себя хочу пожелать - здоровья, счастья и успехов во всех делах, развиваться, быть здоровой клеткой. Берегите себя и своих близких. Пусть безумия станет меньше - мирного неба над головой 🕊
С наступающим 2️⃣0️⃣2️⃣4️⃣ годом! 🎄
Создатель канала Oracle Developer, Кивилёв Денис
Поздравить друг друга в чатике 💬 ☃️
#newyear
На носу у нас новый год 🎄, а значит самое время подвести итоги:
1️⃣ Канал, наконец-то, перевалил цифру в 3000 подписчиков.
Уже давно не занимался его раскруткой, а это значит, что работает сарафанное радио 🗣
2️⃣ Было опубликовано более 100 постов.
Начали подключаться участники канала к написанию контента. Надеюсь эта тенденция сохранится ✏️
3️⃣ В чате сформировалось сообщество, которое готово прийти на помощь советом, кодом, мнением.
Спасибо, ребята!
4️⃣ Я дописал и провел первый поток по курсу "Основы оптимизации Oracle SQL".
Получился довольно качественный продукт, не похожий на аналоги.
5️⃣ И даже, провели первый конкурс 😊
Результаты, которого, пора подвести.
ТОП-3 задачки 🏆
1 место (5К) - сбор мусора Михалычем
2 место (3К) - создание deadlock
3 место (2К) - вывод календаря
отдельный приз (2К) - самый популярный ответ в чате. их было два.
Новогодние подарки победителям уже отправлены 🎁 🎈
Всем спасибо за участие, в следующем году повторим 👍
~~~~
Кстати, это уже четвертый (!) новый год, с которым я поздравляю вас в нашем канале 🥳
От себя хочу пожелать - здоровья, счастья и успехов во всех делах, развиваться, быть здоровой клеткой. Берегите себя и своих близких. Пусть безумия станет меньше - мирного неба над головой 🕊
С наступающим 2️⃣0️⃣2️⃣4️⃣ годом! 🎄
Создатель канала Oracle Developer, Кивилёв Денис
Поздравить друг друга в чатике 💬 ☃️
#newyear
🎉29👍14🔥6❤5
Друзья, всем привет!
Первый пост года начнем с простой вещи.
DBeaver - бесплатная кросс-платформенная IDE для работы с разными СУБД (RDBMS, NoSQL).
И конечно же, её используют наши студенты. Забавно, что второй поток подряд сталкиваются с проблемой слешей в DBeaver.
Т.е. элементарный код:
не выполняется.
IDE ругается на слэши. Это печально 😐
Как это можно исправить?
1. Выбираем коннект к БД, открываем его настройки (Edit connection)
2. Переходим в SQL Editor -> SQL Processing
3. Меняем Statement delimiter на слэш.
4. Наслаждаемся.
Возможно, кому-то станет легче жить 😉
Обсудить в чатике 💬
#ide
Oracle Developer
Первый пост года начнем с простой вещи.
DBeaver - бесплатная кросс-платформенная IDE для работы с разными СУБД (RDBMS, NoSQL).
И конечно же, её используют наши студенты. Забавно, что второй поток подряд сталкиваются с проблемой слешей в DBeaver.
Т.е. элементарный код:
begin
...
end;
/
не выполняется.
IDE ругается на слэши. Это печально 😐
Как это можно исправить?
1. Выбираем коннект к БД, открываем его настройки (Edit connection)
2. Переходим в SQL Editor -> SQL Processing
3. Меняем Statement delimiter на слэш.
4. Наслаждаемся.
Возможно, кому-то станет легче жить 😉
Обсудить в чатике 💬
#ide
Oracle Developer
👍39❤1
Задача. Повторная вставка без exception
Давно не было авторской задачки 😊
Дана табличка:
Повторное выполнение вставки
завершается ошибкой:
ORA-00001: unique constraint (PART.TAB1_PK) violated
Хочется написать запрос так, чтобы повторная вставка не вызывала ошибку. Как это сделать?
Я насчитал, как минимум, 3 способа через SQL и 1 читерский через PL/SQL. Интересует, прежде всего, SQL.
Разбор, как всегда, в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
Давно не было авторской задачки 😊
Дана табличка:
create table tab1(
id number(38),
val varchar2(20 char),
constraint tab1_pk primary key (id)
);
insert into tab1 values (1, 's1');
commit;
Повторное выполнение вставки
insert into tab1 values (1, 's1');
завершается ошибкой:
ORA-00001: unique constraint (PART.TAB1_PK) violated
Хочется написать запрос так, чтобы повторная вставка не вызывала ошибку. Как это сделать?
Я насчитал, как минимум, 3 способа через SQL и 1 читерский через PL/SQL. Интересует, прежде всего, SQL.
Разбор, как всегда, в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
👍2
Задача. Решение. Повторная вставка без exception
Кратко: нужно выполнить повторно insert с таким же PK без возникновения ошибки. Постановка.
1️⃣ Переписать через merge
2️⃣ Использовать хинт (с Oracle 11g)
У хинта есть ограничения, он не всегда подходит. Смотрим документацию.
3️⃣ Использовать опцию log errors в DML
предварительно создаем таблицу для логирования ошибок
подробности в этом посте
4️⃣ Способ читерский (через PL/SQL)
С PL/SQL может быть полет фантазии, но интересовал, прежде всего, SQL.
В чатике коллеги накидали еще вариантов.
А что там в PostgreSQL?
Самое простое решение:
К осени, планирую запустить пилотный поток по основам СУБД PostgreSQL, миграции с Oracle. Кому интересно пишите в личку, ищу 9 человек 😉
————
Понравилась задачка? Ставь 👍
#решениезадачи #exception #dml
Канал Oracle Developer | Чатик 💬
Кратко: нужно выполнить повторно insert с таким же PK без возникновения ошибки. Постановка.
1️⃣ Переписать через merge
merge into tab1 d
using (select 1 id, 's1' val from dual) s
on (d.id = s.id)
when not matched then insert(id, val)
values(s.id, s.val);
2️⃣ Использовать хинт (с Oracle 11g)
insert /*+ ignore_row_on_dupkey_index(tab1(id)) */
into tab1 values (1, 's1');
У хинта есть ограничения, он не всегда подходит. Смотрим документацию.
3️⃣ Использовать опцию log errors в DML
предварительно создаем таблицу для логирования ошибок
call dbms_errlog.create_error_log(
dml_table_name => 'tab1',
err_log_table_name => 'tab1$errlog'
);
insert into tab1 values (1, 's1')
log errors into tab1$errlog reject limit unlimited;
подробности в этом посте
4️⃣ Способ читерский (через PL/SQL)
begin
insert into tab1 values (1, 's1');
exception
when DUP_VAL_ON_INDEX then
null;
end;
/
С PL/SQL может быть полет фантазии, но интересовал, прежде всего, SQL.
В чатике коллеги накидали еще вариантов.
А что там в PostgreSQL?
Самое простое решение:
insert into tab1 values (1, 's1')
on conflict on constraint tab1_pk
do nothing;
К осени, планирую запустить пилотный поток по основам СУБД PostgreSQL, миграции с Oracle. Кому интересно пишите в личку, ищу 9 человек 😉
————
Понравилась задачка? Ставь 👍
#решениезадачи #exception #dml
Канал Oracle Developer | Чатик 💬
👍39
Задача. Реверс инжиниринг текста запроса
Друзья, всем привет!
Как вы знаете, в январе стартовал второй поток по оптимизации. Вчера мы с ребятами разбирали как читать планы запросов, как читать последовательность выполнения операций и т.д. Один из примеров был такой - см. скрин.
Попробуйте по этим данным восстановить план запроса. Скажу сразу этот запрос с особенностью. Если часто с таким не сталкиваетесь будет сложновато.
Ради интереса прогнал через ChatGPT3.5, он сформировал неверный текст запроса 🤖
Разбор задачи в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
Друзья, всем привет!
Как вы знаете, в январе стартовал второй поток по оптимизации. Вчера мы с ребятами разбирали как читать планы запросов, как читать последовательность выполнения операций и т.д. Один из примеров был такой - см. скрин.
Попробуйте по этим данным восстановить план запроса. Скажу сразу этот запрос с особенностью. Если часто с таким не сталкиваетесь будет сложновато.
Ради интереса прогнал через ChatGPT3.5, он сформировал неверный текст запроса 🤖
Разбор задачи в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
👍8❤1
Решение задачи. Реверс инжиниринг текста запроса
Друзья, всем привет!
Итак. Что мы можем сказать по этому плану?
Выполняется 4 операции.
1️⃣ На 3м шаге происходит полное сканирование таблицы employees (table access full). Результат выборки: две колонки email и department_id (см. column projection information для 3). Никаких предикатов нет (нет информации в блоке predicate information для 3), а значит нет условия where.
2️⃣ На 2м шаге происходит доступ к индексу dept_id_pk (index unique scan) по department_id (блок predicate information для 2). Результат выборки: 1 - rowid (из листа уникального индекса при unique scan).
3️⃣ На 1м шаге, по полученному rowid, выбирается одна строка из таблички departments. Результат выборки: department_name.
Ок. У нас есть два множества, полученные на 1м шаге и 3м. Но как они меж собой взаимодействуют?
Если посмотреть в плане нет никаких соединений (join), объединений (union).
Отгадка в последовательности выполнения операций. Человек, который не сталкивается с такими кейсами сказал бы, что последовательность выполнения 2-1-3-0. Но нет 🤷🏻♂️
Это исключение. В данном случае, последовательность 3-2-1-0.
Т.е. для всех строк из шага 3, выполняется 2-1.
Итоговый запрос
Стало ли ясно новичку, о чем я тут?
Довольно сложно с одного поста въехать в тему. Для начала рекомендую посмотреть пост + видео, о том, как определять порядок операций в плане запросов.
Сейчас я бы переделал это видео, но посмотреть все же стоит 😊
Если хочется комплексно подойти к вопросу - велком на курс по оптимизации Oracle SQL. Старт следующего потока - лето 24.
Всем хороших выходных 🌴
#оптимизация #решениезадачи
Канал Oracle Developer | Чатик 💬
Друзья, всем привет!
Итак. Что мы можем сказать по этому плану?
Выполняется 4 операции.
1️⃣ На 3м шаге происходит полное сканирование таблицы employees (table access full). Результат выборки: две колонки email и department_id (см. column projection information для 3). Никаких предикатов нет (нет информации в блоке predicate information для 3), а значит нет условия where.
2️⃣ На 2м шаге происходит доступ к индексу dept_id_pk (index unique scan) по department_id (блок predicate information для 2). Результат выборки: 1 - rowid (из листа уникального индекса при unique scan).
3️⃣ На 1м шаге, по полученному rowid, выбирается одна строка из таблички departments. Результат выборки: department_name.
Ок. У нас есть два множества, полученные на 1м шаге и 3м. Но как они меж собой взаимодействуют?
Если посмотреть в плане нет никаких соединений (join), объединений (union).
Отгадка в последовательности выполнения операций. Человек, который не сталкивается с такими кейсами сказал бы, что последовательность выполнения 2-1-3-0. Но нет 🤷🏻♂️
Это исключение. В данном случае, последовательность 3-2-1-0.
Т.е. для всех строк из шага 3, выполняется 2-1.
Итоговый запрос
select e.email
,(select d.department_name
from departments d
where d.department_id = e.department_id) dep_name
from employees e;
Стало ли ясно новичку, о чем я тут?
Довольно сложно с одного поста въехать в тему. Для начала рекомендую посмотреть пост + видео, о том, как определять порядок операций в плане запросов.
Сейчас я бы переделал это видео, но посмотреть все же стоит 😊
Если хочется комплексно подойти к вопросу - велком на курс по оптимизации Oracle SQL. Старт следующего потока - лето 24.
Всем хороших выходных 🌴
#оптимизация #решениезадачи
Канал Oracle Developer | Чатик 💬
👍14
Задача. Хранение истории заключения договоров
Давно не было задачек на архитектуру 😊
Некая система, допустим, электронный кошелек, должна хранить историю договоров пользователей:
🔸 когда пользователь регистрируется в системе, создается запись о том, что договор активен;
🔸 когда он удаляет свой кошелек, необходимо этот факт отразить в данных;
🔸 регистрация в системе происходит по номеру телефона. Все мы помним, что номер телефона может переиспользоваться со временем;
🔸 иногда нужно искать по номеру телефона, когда он использовался с каким договором в какие периоды;
🔸 ожидается, что всего активных договоров будет около 10 миллионов, а неактивных, со временем, ~100 миллионов и будет расти.
Необходимо создать таблицу (или несколько), которая бы отвечала требованиям выше. Как минимум, должны быть поля:
▫️ ID договора (PK)
▫️ Номер телефона (число, не уникальное)
Разбор задачи в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
Давно не было задачек на архитектуру 😊
Некая система, допустим, электронный кошелек, должна хранить историю договоров пользователей:
🔸 когда пользователь регистрируется в системе, создается запись о том, что договор активен;
🔸 когда он удаляет свой кошелек, необходимо этот факт отразить в данных;
🔸 регистрация в системе происходит по номеру телефона. Все мы помним, что номер телефона может переиспользоваться со временем;
🔸 иногда нужно искать по номеру телефона, когда он использовался с каким договором в какие периоды;
🔸 ожидается, что всего активных договоров будет около 10 миллионов, а неактивных, со временем, ~100 миллионов и будет расти.
Необходимо создать таблицу (или несколько), которая бы отвечала требованиям выше. Как минимум, должны быть поля:
▫️ ID договора (PK)
▫️ Номер телефона (число, не уникальное)
Разбор задачи в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
Медленно меняющееся измерение или Slowly changing dimension (SCD)
Как-то давно мы уже обсуждали подходы по хранению исторических данных. Я решил, немного раскрыть тему.
Основа - статья в Wiki на ENG (больше инфы) и RUS.
Есть некоторое количество подходов к хранению исторических данных. Кратко перечислю.
Тип 0. Данные не меняются
Изменения не фиксируются, т.к. данные в строках/полях не изменяются.
Тип 1. Полная замена
Историчность не соблюдается, новые данные записываются вместо старых. Нет никакой возможности получить предыдущие значения.
💡Этот тип встречается постоянно. Вы его используете по умолчанию.
Тип 2. Вставка новой строки с новой версией данных
Помимо основных полей, в таблице появляются служебные поля, которые обслуживают историю.
Например, столбец “Actual” = {0 - не актуальная версия, 1 - актуальная}. С “1” может быть только одна строка для какого-то конкретного экземпляра сущности. С “0” может быть несколько.
Или две даты, обозначающие период действия строчки - from/to. Для актуальной, самой последней строки, значение в date_to заполняется либо null, либо какой-то заглушкой типа 01.01.4000.
Еще могут быть различные вариации с монотонно растущими версиями и т.п.
Чтобы получить актуальную запись достаточно отфильтровать по столбцам Actual = 1 или date_to = 01.01.4000 или взять максимальную версию.
💡Довольно часто, встречается при решении реальных задач, когда требуется проследить всю историю изменений сущностей.
Тип 3. Добавление доп полей для хранения старых значений
В основной строке мы создаем доп поля, в которых хранятся предыдущие значения.
Как только строка меняется, то в основные поля попадают новые значения, а в доп поля старые значения. Используется такой подход для ограниченного количества полей, только по тем, которые интересует история. Естественно, сохраняется всегда только текущая версия и предыдущая, мы не сможем проследить всю историю изменений.
💡Не прям, частый кейс, но если требуется хранение только текущего и предыдущего значения ограниченного набора полей - почему нет.
Тип 4. Добавление таблицы с историей
В основной таблице хранится самая актуальная информация.
В дополнительной таблице хранятся все изменения. Она повторяет по структуре основную + доп служебные поля (дата изменения, может быть пользователь кто менял и т.п.)
Как только меняется основная таблица, информация тут же помещается в историческую.
💡Довольно часто, этот тип используется в аудитах/логах и т.д.
+ еще три типа, являющиеся разными комбинациями и/или расширениями первых четырех.
У каждого типа есть свои плюсы и минусы и кейсы использования. Рекомендую посмотреть статью на Вики.
К чему это все?
Можно использовать один из подходов для решения вчерашней задачки 😉
#scd #архитектура
Канал Oracle Developer | Чатик 💬
Как-то давно мы уже обсуждали подходы по хранению исторических данных. Я решил, немного раскрыть тему.
Основа - статья в Wiki на ENG (больше инфы) и RUS.
Есть некоторое количество подходов к хранению исторических данных. Кратко перечислю.
Тип 0. Данные не меняются
Изменения не фиксируются, т.к. данные в строках/полях не изменяются.
Тип 1. Полная замена
Историчность не соблюдается, новые данные записываются вместо старых. Нет никакой возможности получить предыдущие значения.
💡Этот тип встречается постоянно. Вы его используете по умолчанию.
Тип 2. Вставка новой строки с новой версией данных
Помимо основных полей, в таблице появляются служебные поля, которые обслуживают историю.
Например, столбец “Actual” = {0 - не актуальная версия, 1 - актуальная}. С “1” может быть только одна строка для какого-то конкретного экземпляра сущности. С “0” может быть несколько.
Или две даты, обозначающие период действия строчки - from/to. Для актуальной, самой последней строки, значение в date_to заполняется либо null, либо какой-то заглушкой типа 01.01.4000.
Еще могут быть различные вариации с монотонно растущими версиями и т.п.
Чтобы получить актуальную запись достаточно отфильтровать по столбцам Actual = 1 или date_to = 01.01.4000 или взять максимальную версию.
💡Довольно часто, встречается при решении реальных задач, когда требуется проследить всю историю изменений сущностей.
Тип 3. Добавление доп полей для хранения старых значений
В основной строке мы создаем доп поля, в которых хранятся предыдущие значения.
Как только строка меняется, то в основные поля попадают новые значения, а в доп поля старые значения. Используется такой подход для ограниченного количества полей, только по тем, которые интересует история. Естественно, сохраняется всегда только текущая версия и предыдущая, мы не сможем проследить всю историю изменений.
💡Не прям, частый кейс, но если требуется хранение только текущего и предыдущего значения ограниченного набора полей - почему нет.
Тип 4. Добавление таблицы с историей
В основной таблице хранится самая актуальная информация.
В дополнительной таблице хранятся все изменения. Она повторяет по структуре основную + доп служебные поля (дата изменения, может быть пользователь кто менял и т.п.)
Как только меняется основная таблица, информация тут же помещается в историческую.
💡Довольно часто, этот тип используется в аудитах/логах и т.д.
+ еще три типа, являющиеся разными комбинациями и/или расширениями первых четырех.
У каждого типа есть свои плюсы и минусы и кейсы использования. Рекомендую посмотреть статью на Вики.
К чему это все?
Можно использовать один из подходов для решения вчерашней задачки 😉
#scd #архитектура
Канал Oracle Developer | Чатик 💬
👍14
Решение задачи. Хранение истории заключения договоров
При решении задачи воспользуемся вторым подходом/типом SCD (см предыдущий пост).
Добавим два поле - дата ОТ и дата ДО действия строки.
Одномоментно, может быть только один активный контракт на один номер телефона. Добавим ограничение:
Активные записи будет помечаться “заглушкой” в date_to = 01.01.4000.
Для деактивации договора, достаточно найти по номеру телефона и “заглушке” актуальную запись и изменить значение в date_to на текущую дату.
При поиске истории по номеру телефона будет использоваться индекс contract_phone_uq:
Для повторной регистрация пользователя и создание нового контракта на номер, который уже был в БД, достаточно опять произвести вставку с "заглушкой".
В целом, мы реализовали то, что хотели. Итоговую историю, можно посмотреть на скриншоте ⬆️
Тут не хватает, некоторых штрихов, которые мы обсудим в следующих постах.
К слову сказать, такой подход неоднократно использовался в реальном банковском софте 👨🏻💻
Палец вверх, если понравилось 👍
#архитектура #решениезадачи
Канал Oracle Developer | Чатик 💬
При решении задачи воспользуемся вторым подходом/типом SCD (см предыдущий пост).
Добавим два поле - дата ОТ и дата ДО действия строки.
create table contract(
contract_id number(38) not null, --PK
phone number(12) not null,
date_from date not null,
date_to date not null
);
Одномоментно, может быть только один активный контракт на один номер телефона. Добавим ограничение:
create unique index contract_phone_uq on contract(phone, date_to);
Активные записи будет помечаться “заглушкой” в date_to = 01.01.4000.
insert into contract values (1,79139331122, sysdate, date'4000-01-01');
insert into contract values (2,79139331155, sysdate, date'4000-01-01');
Для деактивации договора, достаточно найти по номеру телефона и “заглушке” актуальную запись и изменить значение в date_to на текущую дату.
update contract c
set c.date_to = sysdate
where c.phone = 79139331155
and c.date_to = date'4000-01-01';
При поиске истории по номеру телефона будет использоваться индекс contract_phone_uq:
select * from contract t where t.phone = 79139331155;
Для повторной регистрация пользователя и создание нового контракта на номер, который уже был в БД, достаточно опять произвести вставку с "заглушкой".
insert into contract values (3,79139331155, sysdate, date'4000-01-01');
В целом, мы реализовали то, что хотели. Итоговую историю, можно посмотреть на скриншоте ⬆️
Тут не хватает, некоторых штрихов, которые мы обсудим в следующих постах.
К слову сказать, такой подход неоднократно использовался в реальном банковском софте 👨🏻💻
Палец вверх, если понравилось 👍
#архитектура #решениезадачи
Канал Oracle Developer | Чатик 💬
👍28❤1
Друзья, всем привет!
В прошлом году у нас проходил #конкурс с денежными призами на ТОП лучших задачек.
Помните, наверное, про бомжей, календари и другие 😉
Опыт оказался удачным - вам было интересно, коллеги получили денежку 💵
Предлагаю повторить. Всего будет 6 задачек по SQL или PL/SQL.
Призы
1️⃣ Авторам
1 место - 5К, 2 место - 3К, 3 место - 2К рублей.
2️⃣ Активному участнику в чате
Автор ответа (не важно на какую задачу), набравший максимальное количество реакций в чатике, будет так же одарен.
Кто хочет поучаствовать в качестве автора - прошу в личку 👌
Примеры задачек можно посмотреть по хештегу #конкурс
К сожалению, для призового фонда нужна денежка, поэтому реклама еще немного помозолит глаза 🤷🏻♂️
Oracle Developer
#конкурс
В прошлом году у нас проходил #конкурс с денежными призами на ТОП лучших задачек.
Помните, наверное, про бомжей, календари и другие 😉
Опыт оказался удачным - вам было интересно, коллеги получили денежку 💵
Предлагаю повторить. Всего будет 6 задачек по SQL или PL/SQL.
Призы
1️⃣ Авторам
1 место - 5К, 2 место - 3К, 3 место - 2К рублей.
2️⃣ Активному участнику в чате
Автор ответа (не важно на какую задачу), набравший максимальное количество реакций в чатике, будет так же одарен.
Кто хочет поучаствовать в качестве автора - прошу в личку 👌
Примеры задачек можно посмотреть по хештегу #конкурс
К сожалению, для призового фонда нужна денежка, поэтому реклама еще немного помозолит глаза 🤷🏻♂️
Oracle Developer
#конкурс
👍13🎉3❤2
Задача. Удаление ненужных договоров
Вернемся к нашей задаче с договорами.
Бизнес решил, что закрытые договора, старше 5 лет (от даты закрытия), можно удалять из системы.
Данные эти не нужны.
Таблица, которую мы создали:
Уточнения:
🔸 практически все запросы в системе происходят к активным договорам;
🔸 в месяц заключается - 1M договоров, закрывается - 300K.
Какие есть варианты реализации бизнес требований?
Разбор задачи в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
Вернемся к нашей задаче с договорами.
Бизнес решил, что закрытые договора, старше 5 лет (от даты закрытия), можно удалять из системы.
Данные эти не нужны.
Таблица, которую мы создали:
create table contract(
contract_id number(38) not null, --PK
phone number(12) not null,
date_from date not null,
date_to date not null
);
Уточнения:
🔸 практически все запросы в системе происходят к активным договорам;
🔸 в месяц заключается - 1M договоров, закрывается - 300K.
Какие есть варианты реализации бизнес требований?
Разбор задачи в четверг 🎓
Обсудить в чатике 💬
#задача
Oracle Developer
❤3
Решение задачи. Удаление не нужных договоров
При деактивации договора, в поле date_to проставляется текущая дата. Таких договоров, в месяц может быть - 300К.
Эту задачу можно решить, как минимум, двумя способами.
1️⃣ Применить Range-секционирование к таблице по дате закрытия договора - date_to.
Алгоритм: достаточно определить секцию для удаления, выполнить DDL-команду и всё.
➕
▫️ DDL команда на удаление выполнится моментально, практически не создав UNDO\REDO информации и нагрузки на БД.
▫️Активные договора всегда будут находится в самой последней секции с date_to = 01.01.4000. Можем попутно получить плюсы от секционирования, связанные с ускорением выполнения запросов.
▫️Не важно сколько данных удаляется 300К или 300М - всегда будет предсказуемое время работы.
➖
▫️Таблицу необходимо переделать в секционированную, если она уже существует - это может быть проблемой (dbms_redifinition).
▫️Если обращение идет не по глобальному индексу (PK), то во всех запросах необходимо использовать ключ секционирования по date_to, иначе будут перебираться все секции. Запросы придется писать внимательно.
▫️DBA скептически относятся к выполнению DDL-команд на таблицах с глобальными индексами, даже с опцией update global indexes. Могут не пропустить такое решение.
2️⃣ Удалять данные пачками обычным DML
➕
▫️Не надо менять структуру таблицы;
▫️Достаточно простая реализация удаления пачками по N-строк ниже определенной даты.
➖
▫️Создается дополнительная нагрузка на СУБД - генерация UNDO\REDO.
▫️При увеличении удаляемых данных выполнение начнет проседать, необходимо будет увеличивать частоту удалений и размер пачек. В итоге можно воткнуться в потолок, при котором придется переходить на секционирование.
———
И в первом и во втором случаях, функционал заворачивается в процедурку, которая вызывается из JOBа.
С 1м вариантом JOB запускается раз в сутки\несколько раз в месяц, со 2м вариантом чаще, например, раз в 1 час - удаляем мелкими пачками, чтобы распределить нагрузку в течение дня или удаляем всё ночью.
Кстати, можно создать комбинацию из 1го и 2го вариантов 😉
Палец вверх, если понравилось 👍
Обсудить в чатике плюсы и минусы решений 💬
Плаваете в секционировании? Велком в личку, есть что предложить 🎓
#архитектура #решениезадачи #секционирование
Канал Oracle Developer | Чатик 💬
При деактивации договора, в поле date_to проставляется текущая дата. Таких договоров, в месяц может быть - 300К.
Эту задачу можно решить, как минимум, двумя способами.
1️⃣ Применить Range-секционирование к таблице по дате закрытия договора - date_to.
Алгоритм: достаточно определить секцию для удаления, выполнить DDL-команду и всё.
alter table contract drop partition part_name update global indexes;
➕
▫️ DDL команда на удаление выполнится моментально, практически не создав UNDO\REDO информации и нагрузки на БД.
▫️Активные договора всегда будут находится в самой последней секции с date_to = 01.01.4000. Можем попутно получить плюсы от секционирования, связанные с ускорением выполнения запросов.
▫️Не важно сколько данных удаляется 300К или 300М - всегда будет предсказуемое время работы.
➖
▫️Таблицу необходимо переделать в секционированную, если она уже существует - это может быть проблемой (dbms_redifinition).
▫️Если обращение идет не по глобальному индексу (PK), то во всех запросах необходимо использовать ключ секционирования по date_to, иначе будут перебираться все секции. Запросы придется писать внимательно.
▫️DBA скептически относятся к выполнению DDL-команд на таблицах с глобальными индексами, даже с опцией update global indexes. Могут не пропустить такое решение.
2️⃣ Удалять данные пачками обычным DML
delete from contract where date_to < :delete_date and rownum < N;
➕
▫️Не надо менять структуру таблицы;
▫️Достаточно простая реализация удаления пачками по N-строк ниже определенной даты.
➖
▫️Создается дополнительная нагрузка на СУБД - генерация UNDO\REDO.
▫️При увеличении удаляемых данных выполнение начнет проседать, необходимо будет увеличивать частоту удалений и размер пачек. В итоге можно воткнуться в потолок, при котором придется переходить на секционирование.
———
И в первом и во втором случаях, функционал заворачивается в процедурку, которая вызывается из JOBа.
С 1м вариантом JOB запускается раз в сутки\несколько раз в месяц, со 2м вариантом чаще, например, раз в 1 час - удаляем мелкими пачками, чтобы распределить нагрузку в течение дня или удаляем всё ночью.
Кстати, можно создать комбинацию из 1го и 2го вариантов 😉
Палец вверх, если понравилось 👍
Обсудить в чатике плюсы и минусы решений 💬
Плаваете в секционировании? Велком в личку, есть что предложить 🎓
#архитектура #решениезадачи #секционирование
Канал Oracle Developer | Чатик 💬
👍54❤2
Друзья, всем привет! 👋
В этот понедельник закончился уже второй поток курса "Oracle оптимизация SQL. Основы" 🎉
Ребята на протяжении 3.5 месяцев изучали тайны оптимизации СУБД, систематизировали знания, избавляясь от сумбура в голове, практиковались и решали проблемы.
Для меня самое главное, когда в обратной связи в ходе и по завершению курса ребята говорят 💬
🔸"Мне это уже пригодилось на работе"
🔸"У нас был тормозной запрос, а я взял и пофиксил его"
🔸"Вчера ко мне прибежали с проблемой, и буквально за час мы все решили" и т.д.
Прямо музыка для моих ушей. 🎶
Видео-отзывы коллег первого и второго потоков 🎥
Сегодня, чуть позже, анонсирую набор на третий поток.
Всего - 10 мест. 3 уже забронировано. Кто успел того и тапки. Пишите в личку.
#оптимизация #курс
Канал Oracle Developer | Чатик 💬
В этот понедельник закончился уже второй поток курса "Oracle оптимизация SQL. Основы" 🎉
Ребята на протяжении 3.5 месяцев изучали тайны оптимизации СУБД, систематизировали знания, избавляясь от сумбура в голове, практиковались и решали проблемы.
Для меня самое главное, когда в обратной связи в ходе и по завершению курса ребята говорят 💬
🔸"Мне это уже пригодилось на работе"
🔸"У нас был тормозной запрос, а я взял и пофиксил его"
🔸"Вчера ко мне прибежали с проблемой, и буквально за час мы все решили" и т.д.
Прямо музыка для моих ушей. 🎶
Видео-отзывы коллег первого и второго потоков 🎥
Сегодня, чуть позже, анонсирую набор на третий поток.
Всего - 10 мест. 3 уже забронировано. Кто успел того и тапки. Пишите в личку.
#оптимизация #курс
Канал Oracle Developer | Чатик 💬
🔥12👍10❤2