2013-11-16 7 views
1

настоящее время я использую Oracle 11g и скажем, у меня есть таблица со следующими столбцами (более или менее)Альтернативы UPDATE заявление Oracle 11g

Table1

  • ID VARCHAR (64)
  • Статус INT (1)
  • дата TRANSACTION_DATE
  • тонн других колонн

И эта таблица имеет около 1 миллиард рядов. Я хотел бы обновить статус колонку с конкретным где положение, скажем

 


    where transaction_date = somedatehere 

 

Какие альтернативы можно использовать, а не просто нормальное заявление UPDATE?

В настоящее время я пытаюсь сделать, это с помощью CTAS или вставить в выберите, чтобы получить те строки, которые я хочу, чтобы обновить и поставить на другую таблицу, используя AS COLUMN_NAME поэтому значения уже обновлены на новый/временная таблица, которая выглядит примерно так:

 


    INSERT INTO TABLE1_TEMPORARY (
     ID, 
     STATUS, 
     TRANSACTION_DATE, 
     TONS_OF_OTHER_COLUMNS) 
    SELECT 
     ID 
     3 AS STATUS, 
     TRANSACTION_DATE, 
     TONS_OF_OTHER_COLUMNS 
    FROM TABLE1 
    WHERE 
     TRANSACTION_DATE = SOMEDATE 

 

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

То, что я пытался сделать в первой было использовать DELETE на одной и той же исходной таблицы с использованием тех же, где положение так, что в теории, все, что следует оставить в этой таблице должны быть все данные, которые я не нужно обновить, оставив меня теперь с двумя таблицами:

 


    TABLE1 --which now contains the rows that i did not need to update 
    TABLE1_TEMPORARY --which contains the data I updated 

 

Но ВЕЬЕТЕ само по себе также является слишком медленным или медленно, как первоначально заявление UPDATE так без ВЕЬЕТЕ подводит меня к этой точке.

 


    TABLE1 --which contains BOTH the data that I want to update and do not want to update 
    TABLE1_TEMPORARY --which contains the data I updated 

 

Какой другие варианты я могу использовать для того, чтобы получить данные, которые противоположны моя ИНЕКЕ (обратите внимание, что, где положение в этом примере было упрощено, так что я не искал ответ нЕ сУЩЕСТВУЕТ/NOT IN/нЕ РАВНО плюс те пункты медленнее тоже по сравнению с положительными пунктами)

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

Есть ли какая-то инструкция JOIN, которую я использую с моими TABLE1 и TABLE1_TEMPORARY, чтобы отфильтровывать данные, которые не нуждаются в обновлении?

Я также хотел бы достичь этого, используя как можно меньше REDO/UNDO/LOGGING.

Заранее спасибо.

+1

Я думаю, что это странный вопрос. SQL - это декларативный язык. Как правило, все, о чем вы должны беспокоиться, - это описать, что вы хотите. Иногда способ формулирования вашего запроса может иметь последствия для производительности. Однако, в случае чрезвычайно простого заявления о обновлении, как это можно было бы сделать более эффективным, переформулировав его во что-то смехотворно сложное? Может быть, вы хотите реализовать свою собственную СУБД? – wvdz

+2

Вы вообще не описали свою проблему с простым обновлением (что выглядит намного более разумно, чем то, что вы предлагаете). – Mat

+0

Вы хотите удалить миллионы строк, и вы жалуетесь, что это медленно, и оно касается журнала повтора/отмены? Конечно, это является! Конечно, да! –

ответ

1

Я предполагаю, что это не разовая операция, но вы пытаетесь создать повторяющуюся процедуру.

Разделите/разделите таблицу таким образом, чтобы затронутые строки не были полностью распределены по всем разделам, но ограничивались несколькими разделами.

Убедитесь, что ваши транзакции не будут использовать эти разделы на данный момент.

Для каждого раздела/раздела, которое вы обычно ОБНОВЛЯЕТ, выполните CTAS всех строк (я имею в виду, что даже строки, которые остаются неизменными, переходят к TABLE1_TEMPORARY). Затем ОБМЕНАЙТЕ РАЗДЕЛ и перестройте индексные разделы.

В конце перестроить глобальные индексы.

Если у вас нет Oracle Enterprise Edition, вам понадобится либо CTAS всего миллиарда строк (за которым следует ALTER TABLE RENAME, а не ALTER TABLE EXCHANGE PARTITION) или подготовить какое-то «разбиение» бедняка, используя (SELECT UNION ALL SELECT UNION ALL SELECT и т. д.) и набор таблиц.

Существует некоторая вероятность того, что этот беспорядок на самом деле будет быстрее UPDATE.

Я не говорю, что это изящно или оптимально, я говорю, что это канонический способ ускорения больших операций UPDATE в Oracle.

1

Как насчет сохранения в UPDATE в той же таблице, но разбивая ее на несколько небольших кусков?

UPDATE .. WHERE transaction_date = somedatehere AND id BETWEEN 0000000 and 0999999 
COMMIT 
UPDATE .. WHERE transaction_date = somedatehere AND id BETWEEN 1000000 and 1999999 
COMMIT 
UPDATE .. WHERE transaction_date = somedatehere AND id BETWEEN 2000000 and 2999999 
COMMIT 

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

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

Смежные вопросы