powered by simpleCommunicator - 2.0.29     © 2024 Programmizd 02
Map
Форумы / Oracle [игнор отключен] [закрыт для гостей] / аск фор кодривью :)
25 сообщений из 71, страница 1 из 3
аск фор кодривью :)
    #40114471
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Научите уму-разуму, как надо было делать и что плохого в моей реализации.

Постановка задачи:
есть табл tablitchka с количеством записей 1 000 000 000. В таблице нет индексов кроме первичного ключа
Требуется проапдейтить таблицу по условию COND (условие на неиндексированные поля) установив поле kolonka в 1, прогнозируемое количество попадающих под апдейт - 10 000 000.

Мое решение:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
declare
 
   type tp is record (rid rowid, id number);
   type tAr is table of tp;
   ar tar;
   cursor c is
   select t.rowid, t.id from
   tablitchka t
   where /*условие COND*/
    .. and kolonka = 0;               
begin
  open c;
  loop
     fetch c bulk collect  into ar limit 10000; 
     forall i in 1..ar.count save exceptions
     
     update
     tablitchka  --
     SET kolonka = 1 where rowid = ar(i).rid and id = ar(i).id;
     cnt := cnt + sql%rowcount;
     commit;
     exit when c%notfound;
  end loop;
 
  close c; 
 
exception when others then
   null;    
end;



не очень мне нравится, но это единственный вариант который смог извергнуть. Прошу критики и рассказа о правильном подходе
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114472
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ctas [+partitioning] + rename + grants.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114474
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg,

если
напр kolonka = 2 проапдейтить надо?


ps
имхо
если есть условие по ровид, то по ид лишнее

.....
stax
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114475
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKad
ctas
- отказался от такого варианта, тк решил что на работающей базе (таблица активно используется другими сессиями) так не прокатит. важное уточнение - забыл сразу дописать
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114479
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
legg,

если
напр kolonka = 2 проапдейтить надо?
stax

нет
Stax

ps
имхо
если есть условие по ровид, то по ид лишнее

.....
stax

имхо тоже, коллега вцепился зубами в ногу, боится что у записи rowid поменяется в одном случае из стотыщмиллионов. Надеюсь это успокоит
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114489
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg

имхо тоже, коллега вцепился зубами в ногу, боится что у записи rowid поменяется в одном случае из стотыщмиллионов. Надеюсь это успокоит

допустим поменяется ровид и ....

тогда условие rowid = ar(i).rid and id = ar(i).id; не отработает (0 на 1 не поменяется)

ps
есть save exceptions, а обработка за циклом

....
stax
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114498
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg
отказался от такого варианта, тк решил что на работающей базе (таблица активно используется другими сессиями) так не прокатит. важное уточнение - забыл сразу дописать
Есть вариант похардовее.

1) С учетом того, таблица, как и любой сегмент, состоит из экстентов, в цикле с помощью dbms_rowid получаешь первый и последний rowid для каждого экстента и делаешь update по условию
Код: plsql
1.
where your_fucking_condition and rowid between r_begin and r_end

например, с фиксацией транзакции после каждого или N-го экстента.
2) Делаешь финальный update-скан по всей таблице только для тех записей, что были добавлены или мигрированы с момента старта этапа 1 и для которых выполняется условие
Код: plsql
1.
where your_fucking_condition and lnnvl(kolonka = 1)


Какой в этом профит в сравнении с твоим вариантом - не нужно вычитывать таблицу перед обновлением.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114502
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
legg

имхо тоже, коллега вцепился зубами в ногу, боится что у записи rowid поменяется в одном случае из стотыщмиллионов. Надеюсь это успокоит

допустим поменяется ровид и ....

тогда условие rowid = ar(i).rid and id = ar(i).id; не отработает (0 на 1 не поменяется)

ps
есть save exceptions, а обработка за циклом

....
stax

да, верное замечание. просто долго описывать все нюансы. логика - 'если случилась неведомая фигня - лучше ничего трогать не буду, надо ручками разбирать что там.' - в данном случае так можно. и вместо null в обработчике логирование варнинга идет
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114503
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKad
legg
отказался от такого варианта, тк решил что на работающей базе (таблица активно используется другими сессиями) так не прокатит. важное уточнение - забыл сразу дописать
Есть вариант похардовее.

1) С учетом того, таблица, как и любой сегмент, состоит из экстентов, в цикле с помощью dbms_rowid получаешь первый и последний rowid для каждого экстента и делаешь update по условию
Код: plsql
1.
where your_fucking_condition and rowid between r_begin and r_end


например, с фиксацией транзакции после каждого или N-го экстента.
2) Делаешь финальный update-скан по всей таблице только для тех записей, что были добавлены или мигрированы с момента старта этапа 1 и для которых выполняется условие
Код: plsql
1.
where your_fucking_condition and lnnvl(kolonka = 1)



Какой в этом профит в сравнении с твоим вариантом - не нужно вычитывать таблицу перед обновлением.


крутокрутокруто! попробую. сейчас оставлю так, а в след релизе глядишь и эту версию выпущу. на сам деле я чего то подобного и хотел, не знал как реализовать.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114518
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg

вместо null в обработчике логирование варнинга идет


я не про null

я про место обработки, следующие 10000 не обработаются если была "ошибка"


зы
я так понимаю ето разовая операция,
"оптимизация" займет больше времени чем проапдейтить 10млн
stax
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114520
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Stax#22400192]
legg

вместо null в обработчике логирование варнинга идет


я не про null

я про место обработки, следующие 10000 не обработаются если была "ошибка"


ну да. эта процедура будет вызываться ежедневно джобом. по полю kolonka идет партиционирование. конечная цель - перенос из исходной таблицы в целевую неактуальных данных (архивировать то есть) на лету, без техперерывов всяких.
после апдейта kolonka неактуальные данные будут оказываться в другой партиции, которая после копирования будет транкейтиться. так вот - если вдруг что то пошло не так -я решил что надежнее плюнуть и попробовать архивировать в след раз, а в этой итерации забить и не апдейтить.
насколько я понимаю rowid может поменяться только при серьезном каком-то перетряхивании таблиц. при разовых работах. и если такие работы ведутся во время архивирования -ну его на фиг , архивирование. завтра сделаем , а сейчас лучше прекратить свою активность

попытался связанно объяснить, но не уверен что вышло).

Stax

"зы
я так понимаю ето разовая операция,
"оптимизация" займет больше времени чем проапдейтить 10млн
stax " stax
- нет. ежедневно по паре десятков таблиц. с перспективой увеличения количества как таблиц так и их объемов.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114528
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg
по полю kolonka идет партиционирование. конечная цель - перенос из исходной таблицы в целевую неактуальных данных (архивировать то есть) на лету, без техперерывов всяких.

Через row movement?
Мсье знает толк в извращениях.

https://docs.oracle.com/en/database/oracle/oracle-database/19/vldbg/manage-data-db-ilm.html#GUID-C53B27F1-7E71-4683-A2A0-3DE194A59C2E
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114530
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
legg
по полю kolonka идет партиционирование. конечная цель - перенос из исходной таблицы в целевую неактуальных данных (архивировать то есть) на лету, без техперерывов всяких.

Через row movement?
Мсье знает толк в извращениях.

согласен. через row movement естественно. не я это придумал. но реализовываю -я). а тут грабля на грабле.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114533
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник


первый раз вижу о такой возможности. вечером почитаю. спасибо огромное!
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114537
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg


первый раз вижу о такой возможности. вечером почитаю. спасибо огромное!

толи я не туда смотрю, но только я че та не уверен что тут есть то что надо. архивировать можно записи по довольно сложным условиям. к примеру документы могут архивироваться только после того как закрыт соответствующий счет (и еще ряд условий). такие условия разве можно политиками описать? или я не туда поперся?
кажется то что надо. буду вкуривать.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114538
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg

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


имхо
тогда и мало смысла в save exceptions

.....
stax
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114539
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
legg

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


имхо
тогда и мало смысла в save exceptions

.....
stax

я там ругаюсь)
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114571
kapelan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А зачем вообше такая странная логика:
1. Скопировать втаблицу в память
2. Сканировать таблицу в памяти
3. Апдейтить оригинальную таблицу
Вроде-как по всем книжкам гораздо быстрее работать напрямую
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114587
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kapelan
Вроде-как по всем книжкам гораздо быстрее работать напрямую

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

Если натравить update на большую меняющуюся таблицу с ограничителем по числу строк (...and rownum < :BatchSize), то FTS будет бегать каждый запуск. При этом конкуренция и statement restart тоже никуда не денутся.

Примечение: В случае ТС если "самопалить", то надо гонять не update, а delete...returning с последующим выходом на forall insert, это будет дешевле update+row_movement.
Впрочем, означенные выше проблемы delete-у тоже свойственны.


Есть вариант распараллелить dml несколько снижая проблемы с конкуренцией, но не уверен что ТС это надо.

На круг предложенный вариант с разбиением работы на части посредством предварительного анализа таблицы экстентов вполне себе неплох.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114593
kapelan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
kapelan
Вроде-как по всем книжкам гораздо быстрее работать напрямую

Прямая прямой рознь....

это все понятно, тока переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ...
Грубо говоря получаем двойной фулл скан большой таблицы.
Я бы посмотрел в в сторону мат. вью: навесить на него нужные индексы и делать поиск по индексам.
Таким образом получаем поиск по индексу в мат. вью и UPDATE таблицы по PRIMARY KEY
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114598
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kapelan
переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ...

Это о чем?
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114607
kapelan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
kapelan
переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ...

Это о чем?


Код: plsql
1.
2.
     fetch c bulk collect  into ar limit 10000; 
     forall i in 1..ar.count save exceptions
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114611
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kapelan
andrey_anonymous
пропущено...

Это о чем?


Код: plsql
1.
2.
     fetch c bulk collect  into ar limit 10000; 
     forall i in 1..ar.count save exceptions


или я чего то не понимаю или выглядит так, что вы сравниваете скорость чтения с диска данных таблицы и скорость перебора массива в оперативной памяти.
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114615
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kapelan
andrey_anonymous
пропущено...

Прямая прямой рознь....

это все понятно, тока переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ...
Грубо говоря получаем двойной фулл скан большой таблицы.
Я бы посмотрел в в сторону мат. вью: навесить на него нужные индексы и делать поиск по индексам.
Таким образом получаем поиск по индексу в мат. вью и UPDATE таблицы по PRIMARY KEY

вопрос в том как одним махом проапдейтить 10 000 000 строк. база не в монопольном доступе, очередные 10000000 записей как раз в таблицу инсертятся в это время. а чуть позже - апдейтятся. даже если конкуренций не случится -снапшот ту олд практически гарантирован ведь при прямом апдейте всего сразу?
...
Рейтинг: 0 / 0
аск фор кодривью :)
    #40114620
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg
...
или я чего то не понимаю или выглядит так, что вы сравниваете скорость чтения с диска данных таблицы и скорость перебора массива в оперативной памяти.

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

Кроме того, с транзакционной точки зрения, вы совершаете логическую ошибку,
не блокируя прочитанные вашим первым чтением данные.
После исключения логических ошибок ваш код, может быть, просто поставит базу колом на какое-то количество часов.
...
Рейтинг: 0 / 0
25 сообщений из 71, страница 1 из 3
Форумы / Oracle [игнор отключен] [закрыт для гостей] / аск фор кодривью :)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]