|
|
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
Всем добра! Не хочу ударяться в детали стоящей передо мной задачи, их многовато =) Промежуточная задача - выбрать один из подходов для временного хранения данных переменной структуры в рамках жизни одной процедуры. Задача: Должна быть реализована универсальная процедура, работающая с любыми парами таблиц, если эти таблицы отвечают определенным требованиям. назовем их таблица А и таблица В. Структура у них одинаковая. Таблица В может быть любого, даже самого гигантского размера. Таблица А обычно не больше миллиона строк, но изредка может быть и 10 миллионов. В будущем системы запланирован рост числа данных. В промежуточной таблице процедура сохраняет (на время сессии) rowid строк обеих таблиц, которые будут затронуты изменением. В процедуре динамически формируется запрос, который формирует на основе данных обеих таблиц новые правильные строки для таблицы В. Часть из них пойдет как новые, а часть уже присутствует в В в неправильном виде. В том числе неправильным может считаться и одно из ключевых полей. Т.о. можно удалить из таблицы B все связанные строки и вставить туда результат запроса. Точнее, сначала вставить новые, т.к. в запросе используются данные B, а потом удалить старые уже не нужные. Тут возникает препятствие в виде уникального индекса, который не дает вставить часть новых строк из-за пересечения по ключу. И появляется два принципиальных варианта: 1. использовать merge по B.rowid, при котором для части строк (заранее неизвестно, для части какого/соотношения) будет апдейт с вероятным изменением одного из полей уникального ключа. 2. положить результат запроса в промежуточную структуру, удалить по rowid все связанные строки из В, вставить в В из промежуточной структуры. Лично я склоняюсь к варианту 2. но тут опять возникают варианты: 2.1. создать и в дальнейшем использовать некую таблицу С, повторяющую В, но хранящую только результат запроса. Может быть, temporary table. Возражение - Еще одна постоянная структура в базе, когда и так есть таблицы А, созданные специально для этой цели. 2.2. в процессе работы процедуры создавать таблицу С, а потом дропать ее за собой. 2.3. динамически создавать коллекцию, вставлять туда данные, потом извлекать через forall или table(). Эти три варианта выглядят несколько безумно =) поэтому я начинаю склоняться к первоначальному варианту 1. или 2.2., потому что он наиболее прост с точки зрения понимания работы (когда я открою эту процедуру через год и начну читать комментарии). В общем, как вы считаете, что лучше выбрать? Насколько merge лучше или хуже, чем insert+delete+insert? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.11.2017, 20:27 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
1. merge не позволит обновить ключ, по которому проводится соединение. 2. индекс можно сделать неуникальным, что позволит повесить deferrable primery key и обойти проблему с дублями в пределах одной транзакции. 3. можно merge-ить все изменения, не затрагивающие ключ, а операции с изменением PK прогонять отдельно простым update. 4. если есть возможность гарантировать отсутствие постороннего DML во время операции, то можно пройти путем - create Z as select from b, a, c - exchange partition with b including indexes without validation - drop Z 5. На самом деле очень мало что мешает сначала удалять затронутые строки, а затем вставлять - все равно целевой набор готовите "сбоку" (вариация на тему 4). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.11.2017, 21:20 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
у меня, видимо, не получилось нормально описать. если будет merge, он будет соединять целевую таблицу и то, что в using, по rowid, поэтому проблемы с обновлением ключа как таковой нет, все выполнится. с exchange partition хорошая идея, но она является развитием варианта "создать таблицу, использовать, дропнуть". а я как раз и не могу понять, насколько эта идея плоха. какие могут быть подводные камни в таком подходе? кроме одновременного запуска по одной и той же паре таблиц (это решаемо) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 13:15 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
chidoriami"создать таблицу, использовать, дропнуть". а я как раз и не могу понять, насколько эта идея плоха. какие могут быть подводные камни в таком подходе? Если много-много раз так делать, то может попухнуть словарь. Но это тоже не проблема, если дроп заменить truncate-ом, а create - insert append-ом ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 15:06 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
И да, хранить (persistence) rowid - в общем случае нездоровая идея. Однажды между операциями подготовки промежуточных объектов и merge-ем случится какой-нибудь alter table move и при неудачном стечении звезд результат может оказаться... неожиданным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 15:08 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
я не храню rowid на постоянной основе авторВ промежуточной таблице процедура сохраняет ( на время сессии ) rowid строк обеих таблиц авторможет попухнуть словарь мм.. это как? в смысле, в самой таблице словаря в блоках будет много пустого места от такого подхода? оракл что-нибудь делает сам со своими словарями в таком случае или за этим дба должны следить? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 15:19 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
andrey_anonymousИ да, хранить (persistence) rowid - в общем случае нездоровая идея. Однажды между операциями подготовки промежуточных объектов и merge-ем случится какой-нибудь alter table move и при неудачном стечении звезд результат может оказаться... неожиданным. по описанию подходов понятно одно - никто кроме автора с этими таблицами параллельно работать не будет ))) ну а если будет, то сам виноват ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 16:33 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
ну это DWH =)) во время загрузки такого не делают по определению))) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 16:35 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
в смысле, move'ов не делают. а одновременного наката изменений на таблицу тоже не будет, уже по ограничениям архитектуры ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 16:39 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
DВАну а если будет, то сам виноват Так "он" ТС-у подгадит, а не "сам виноват" :) Причем ошибку могут обнаружить и совсем не сразу. ...помимо alter tble бывает еще rowmovement, тоже не следует забывать. Впрочем, если целевую таблицу залочить перед операцией, набор готовить "сбоку" посредством insert select, а завершать транзакцию exchange partition - может получиться вменяемая конструляция. А вот merge по rowid не одобряю, и все тут :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 17:55 |
|
||
|
Подводные камни create drop для временного хранения данных
|
|||
|---|---|---|---|
|
#18+
andrey_anonymousА вот merge по rowid не одобряю, и все тут :)В DWH это нормально и позволяет уменьшить накладные расходы за счет отсутствия необходимости дергать индексы или удобно параллелить вручную, но только если объем изменений не слишком высок, иначе эффективнее будут вариации этого: andrey_anonymous4. если есть возможность гарантировать отсутствие постороннего DML во время операции, то можно пройти путем - create Z as select from b, a, c - exchange partition with b including indexes without validation - drop Z ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2017, 18:08 |
|
||
|
|

start [/forum/topic.php?fid=52&tid=1884977]: |
0ms |
get settings: |
6ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
47ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
42ms |
get tp. blocked users: |
1ms |
| others: | 207ms |
| total: | 332ms |

| 0 / 0 |
