|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
Научите уму-разуму, как надо было делать и что плохого в моей реализации. Постановка задачи: есть табл 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.
не очень мне нравится, но это единственный вариант который смог извергнуть. Прошу критики и рассказа о правильном подходе ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 11:48 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
ctas [+partitioning] + rename + grants. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 11:54 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg, если напр kolonka = 2 проапдейтить надо? ps имхо если есть условие по ровид, то по ид лишнее ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 12:02 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
AmKad ctas ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 12:05 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
Stax legg, если напр kolonka = 2 проапдейтить надо? stax нет Stax ps имхо если есть условие по ровид, то по ид лишнее ..... stax имхо тоже, коллега вцепился зубами в ногу, боится что у записи rowid поменяется в одном случае из стотыщмиллионов. Надеюсь это успокоит ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 12:16 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg имхо тоже, коллега вцепился зубами в ногу, боится что у записи rowid поменяется в одном случае из стотыщмиллионов. Надеюсь это успокоит допустим поменяется ровид и .... тогда условие rowid = ar(i).rid and id = ar(i).id; не отработает (0 на 1 не поменяется) ps есть save exceptions, а обработка за циклом .... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 12:52 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg отказался от такого варианта, тк решил что на работающей базе (таблица активно используется другими сессиями) так не прокатит. важное уточнение - забыл сразу дописать 1) С учетом того, таблица, как и любой сегмент, состоит из экстентов, в цикле с помощью dbms_rowid получаешь первый и последний rowid для каждого экстента и делаешь update по условию Код: plsql 1.
например, с фиксацией транзакции после каждого или N-го экстента. 2) Делаешь финальный update-скан по всей таблице только для тех записей, что были добавлены или мигрированы с момента старта этапа 1 и для которых выполняется условие Код: plsql 1.
Какой в этом профит в сравнении с твоим вариантом - не нужно вычитывать таблицу перед обновлением. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 13:16 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
Stax legg имхо тоже, коллега вцепился зубами в ногу, боится что у записи rowid поменяется в одном случае из стотыщмиллионов. Надеюсь это успокоит допустим поменяется ровид и .... тогда условие rowid = ar(i).rid and id = ar(i).id; не отработает (0 на 1 не поменяется) ps есть save exceptions, а обработка за циклом .... stax да, верное замечание. просто долго описывать все нюансы. логика - 'если случилась неведомая фигня - лучше ничего трогать не буду, надо ручками разбирать что там.' - в данном случае так можно. и вместо null в обработчике логирование варнинга идет ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 13:30 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
AmKad legg отказался от такого варианта, тк решил что на работающей базе (таблица активно используется другими сессиями) так не прокатит. важное уточнение - забыл сразу дописать 1) С учетом того, таблица, как и любой сегмент, состоит из экстентов, в цикле с помощью dbms_rowid получаешь первый и последний rowid для каждого экстента и делаешь update по условию Код: plsql 1.
например, с фиксацией транзакции после каждого или N-го экстента. 2) Делаешь финальный update-скан по всей таблице только для тех записей, что были добавлены или мигрированы с момента старта этапа 1 и для которых выполняется условие Код: plsql 1.
Какой в этом профит в сравнении с твоим вариантом - не нужно вычитывать таблицу перед обновлением. крутокрутокруто! попробую. сейчас оставлю так, а в след релизе глядишь и эту версию выпущу. на сам деле я чего то подобного и хотел, не знал как реализовать. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 13:32 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg вместо null в обработчике логирование варнинга идет я не про null я про место обработки, следующие 10000 не обработаются если была "ошибка" зы я так понимаю ето разовая операция, "оптимизация" займет больше времени чем проапдейтить 10млн stax ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:06 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
[quot Stax#22400192] legg вместо null в обработчике логирование варнинга идет я не про null я про место обработки, следующие 10000 не обработаются если была "ошибка" ну да. эта процедура будет вызываться ежедневно джобом. по полю kolonka идет партиционирование. конечная цель - перенос из исходной таблицы в целевую неактуальных данных (архивировать то есть) на лету, без техперерывов всяких. после апдейта kolonka неактуальные данные будут оказываться в другой партиции, которая после копирования будет транкейтиться. так вот - если вдруг что то пошло не так -я решил что надежнее плюнуть и попробовать архивировать в след раз, а в этой итерации забить и не апдейтить. насколько я понимаю rowid может поменяться только при серьезном каком-то перетряхивании таблиц. при разовых работах. и если такие работы ведутся во время архивирования -ну его на фиг , архивирование. завтра сделаем , а сейчас лучше прекратить свою активность попытался связанно объяснить, но не уверен что вышло). Stax "зы я так понимаю ето разовая операция, "оптимизация" займет больше времени чем проапдейтить 10млн stax " stax ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:19 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
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 ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:34 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
andrey_anonymous legg по полю kolonka идет партиционирование. конечная цель - перенос из исходной таблицы в целевую неактуальных данных (архивировать то есть) на лету, без техперерывов всяких. Через row movement? Мсье знает толк в извращениях. согласен. через row movement естественно. не я это придумал. но реализовываю -я). а тут грабля на грабле. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:40 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
andrey_anonymous первый раз вижу о такой возможности. вечером почитаю. спасибо огромное! ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:46 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg andrey_anonymous первый раз вижу о такой возможности. вечером почитаю. спасибо огромное! толи я не туда смотрю, но только я че та не уверен что тут есть то что надо. архивировать можно записи по довольно сложным условиям. к примеру документы могут архивироваться только после того как закрыт соответствующий счет (и еще ряд условий). такие условия разве можно политиками описать? или я не туда поперся? кажется то что надо. буду вкуривать. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:52 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg - если вдруг что то пошло не так -я решил что надежнее плюнуть и попробовать архивировать в след раз, а в этой итерации забить и не апдейтить. имхо тогда и мало смысла в save exceptions ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:57 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
Stax legg - если вдруг что то пошло не так -я решил что надежнее плюнуть и попробовать архивировать в след раз, а в этой итерации забить и не апдейтить. имхо тогда и мало смысла в save exceptions ..... stax я там ругаюсь) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 14:58 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
А зачем вообше такая странная логика: 1. Скопировать втаблицу в память 2. Сканировать таблицу в памяти 3. Апдейтить оригинальную таблицу Вроде-как по всем книжкам гораздо быстрее работать напрямую ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 16:14 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
kapelan Вроде-как по всем книжкам гораздо быстрее работать напрямую Прямая прямой рознь. Если тупо натравить update на большую меняющуюся таблицу, то можете нарваться на statement restart, что в случае большой таблицы будет печально само по себе. Кроме того, update будет длительным и имеет шансы заблокировать основные операции по таблице. Если натравить update на большую меняющуюся таблицу с ограничителем по числу строк (...and rownum < :BatchSize), то FTS будет бегать каждый запуск. При этом конкуренция и statement restart тоже никуда не денутся. Примечение: В случае ТС если "самопалить", то надо гонять не update, а delete...returning с последующим выходом на forall insert, это будет дешевле update+row_movement. Впрочем, означенные выше проблемы delete-у тоже свойственны. Есть вариант распараллелить dml несколько снижая проблемы с конкуренцией, но не уверен что ТС это надо. На круг предложенный вариант с разбиением работы на части посредством предварительного анализа таблицы экстентов вполне себе неплох. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 16:30 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
andrey_anonymous kapelan Вроде-как по всем книжкам гораздо быстрее работать напрямую Прямая прямой рознь.... это все понятно, тока переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ... Грубо говоря получаем двойной фулл скан большой таблицы. Я бы посмотрел в в сторону мат. вью: навесить на него нужные индексы и делать поиск по индексам. Таким образом получаем поиск по индексу в мат. вью и UPDATE таблицы по PRIMARY KEY ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 16:40 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
kapelan переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ... Это о чем? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 16:47 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
andrey_anonymous kapelan переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ... Это о чем? Код: plsql 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 17:05 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
kapelan andrey_anonymous пропущено... Это о чем? Код: plsql 1. 2.
или я чего то не понимаю или выглядит так, что вы сравниваете скорость чтения с диска данных таблицы и скорость перебора массива в оперативной памяти. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 17:15 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
kapelan andrey_anonymous пропущено... Прямая прямой рознь.... это все понятно, тока переложить большую таблицу в другое место тоже не быстрая операция ... потом сканировать ее в памяти ... Грубо говоря получаем двойной фулл скан большой таблицы. Я бы посмотрел в в сторону мат. вью: навесить на него нужные индексы и делать поиск по индексам. Таким образом получаем поиск по индексу в мат. вью и UPDATE таблицы по PRIMARY KEY вопрос в том как одним махом проапдейтить 10 000 000 строк. база не в монопольном доступе, очередные 10000000 записей как раз в таблицу инсертятся в это время. а чуть позже - апдейтятся. даже если конкуренций не случится -снапшот ту олд практически гарантирован ведь при прямом апдейте всего сразу? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 17:21 |
|
аск фор кодривью :)
|
|||
---|---|---|---|
#18+
legg ... или я чего то не понимаю или выглядит так, что вы сравниваете скорость чтения с диска данных таблицы и скорость перебора массива в оперативной памяти. Вы делаете тройную работу - два раза читаете блоки данных в буфере данных, и еще перебираете массив. При этом второе чтение у вас всегда сопровождается проверкой - не надо ли соответствующий блок еще раз прочитать в память. Кроме того, с транзакционной точки зрения, вы совершаете логическую ошибку, не блокируя прочитанные вашим первым чтением данные. После исключения логических ошибок ваш код, может быть, просто поставит базу колом на какое-то количество часов. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.11.2021, 17:30 |
|
|
start [/forum/topic.php?fid=52&fpage=8&tid=1879734]: |
0ms |
get settings: |
17ms |
get forum list: |
5ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
47ms |
get topic data: |
7ms |
get forum data: |
1ms |
get page messages: |
444ms |
get tp. blocked users: |
1ms |
others: | 359ms |
total: | 883ms |
0 / 0 |