Actualizar todas las filas


12

Quiero saber la manera más eficiente de actualizar cada fila en una tabla Oracle extremadamente grande para una sola columna. Por ejemplo:

update mytable set mycolumn=null;

o:

update mytable set mycolumn=42;

Mi conocimiento puede muy bien ser rancio. Lo que hago es alterar la tabla para soltar la columna. Luego, modifico la tabla para agregar la columna con un valor predeterminado del nuevo valor que quiero usar. Luego, modifico la tabla para eliminar el valor predeterminado de la columna. Creo que esto es mucho más rápido que simplemente ejecutar una actualización, pero tengo la sensación de que hay un método mejor.


Según tengo entendido, agregar una nueva columna no nula con un valor predeterminado es un cambio de metadatos solo en Oracle. Dudo que hayan optimizado el caso de "actualizar todas las filas al mismo valor". ¿Es esta una operación común para ti?
Martin Smith

1
Simplemente pruebe ambos métodos y cronometre. ¿Qué te impide hacer esto? ¡Mira el hecho de que debes terminar con el mismo resultado, no con un resultado diferente! De lo contrario, la comparación no es válida.
tvCa

@tvCa He intentado en ambos sentidos. Si solo hago una actualización, se ejecuta durante aproximadamente dos horas y luego la mato. Si suelto una columna, solo me llevará unos segundos. Agregar una columna sin un valor predeterminado (que anula la columna) solo lleva unos segundos. Agregar una columna con un valor predeterminado tarda unos 30 minutos. Entonces, si quiero, por ejemplo, establecer todos los valores de una columna en 'Algún valor', actualmente elimino y agrego la columna. Solo quiero saber si hay una forma más rápida de hacerlo.
kainaw

2
¿Estás usando 11gR2? @MartinSmith es correcto. Consulte aquí para obtener una descripción sobre cómo agregar la nueva columna con DEFAULT como NOT NULL es un cambio mucho más rápido que agregarlo como NULL, lo que forzará una actualización de todas las filas de la tabla (al igual que emitir una instrucción UPDATE). El problema que veo es eliminar el valor PREDETERMINADO después, porque el aumento del rendimiento proviene de almacenar el PREDETERMINADO en el diccionario. También tendrá que lidiar con la restricción NOT NULL en ese punto.
ansible

Respuestas:


2

Mucho depende de la otra actividad en esta tabla mientras realiza esta actualización masiva. Espero que tenga algún tipo de entorno de prueba donde pueda ejecutar algunas muestras de lo que le gustaría hacer y tener una idea de cuál es la mejor manera. Lo intentaré:

  1. Ejecute el single update table set column_name = blah;
  2. Cree un bucle plSql para seleccionar todas las claves primarias de la tabla y recorrerlas, updating the column=blahy confirmar cada X actualizaciones (tal vez 10000). Puede paralelizar este código copiándolo y haciéndolo copiar en una sección separada de Claves primarias.

Tuvimos un problema muy similar con una tabla que se usó de manera muy activa en el sistema OLTP y pudimos paralelizarla 5x y se ejecutó sin que el usuario bloqueara el impacto en una tabla de filas de más de 100 MM que se comprometía cada 10000. No dijo cómo qué tamaño tiene su mesa o qué tipo de aplicación está ejecutando, pero este tipo de solución puede ser adecuada para usted.


0

Para un ayuno UPDATE, asegúrese de no tener ningún disparador que se esté disparando.

SELECT trigger_name, status FROM user_triggers WHERE table_name = 'MYTABLE';

ALTER TABLE mytable DISABLE ALL TRIGGERS;

Asegúrese de volver a habilitar solo los que desee cuando haya terminado.

ALTER TRIGGER mytrigger ENABLE;

También es posible que se encuentre con la sobrecarga del mantenimiento del índice. Intente reconstruir sus índices por separado. Para hacer eso, la respuesta aquí por pappes debería ser útil: /programming/129046/disable-and-later-enable-all-table-indexes-in-oracle

Estoy repitiendo la respuesta de pappes aquí como referencia. (Tenga en cuenta que este comando SPOOL hace suposiciones sobre su plataforma y entorno).

set pagesize 0    
alter session set skip_unusable_indexes = true;
spool c:\temp\disable_indexes.sql
select 'alter index ' || u.index_name || ' unusable;' from user_indexes u;
spool off
@c:\temp\disable_indexes.sql

Importar ...

select 'alter index ' || u.index_name || ' rebuild online;'
  from user_indexes u;

-1

eliminar el índice actualizar la columna Devuelve el índice. pero si la columna contiene el mismo valor para todas las filas, puede soltar el índice.


-2

Si no tiene limitación de espacio, puede crear una nueva tabla, igual que su tabla con su nueva columna agregada a esa tabla y eliminar la tabla anterior:

create new_table as
select old_table.*, (with or without default_Value) as new_column
from old_table;

1
¿Será esto más eficiente? ¿Por qué? ¿Y qué pasa si hay FK que hacen referencia a la tabla existente?
ypercubeᵀᴹ

sí, puede probarlo en otra tabla de muestra y ver el resultado usted mismo. Si hay FK, no lo sé exactamente, pero puede deshabilitarlas y habilitarlas si es eficiente.
E_Salamon

-3

Pruebe varias secuencias de actualización / confirmación. Insertar / Actualizar / Eliminar demasiadas filas sin una confirmación conduce a una gran carga de E / S. Se puede optimizar bastante conociendo los tamaños de bloque y los tamaños de registro y demás.

Para eliminar datos completos en una tabla, truncate table xes mejor que delete from x. También la purga crea otra carga de trabajo de proceso.

Editar: puede usar la inmemoryopción, cargar la tabla en la memoria en formato de columna y luego realizar la actualización. realmente depende de las relaciones y la estructura de su base de datos. Ver este artículo .


3
Quieren actualizar una columna de la tabla. No veo cómo truncateo deletesería de alguna ayuda.
ypercubeᵀᴹ

@ypercube Acabo de explicar cómo la manipulación de datos múltiples sin confirmación conduce a una carga de E / S no deseada; ya sea actualizar u otros OLTP.
Astuto

3
¿Podría explicar con qué frecuencia las confirmaciones reducen las E / S? ¿No aumentarían las E / S debido a los puntos de control?
mustaccio

3
El uso de terminología no convencional ("tx journal", "vacia la sesión") es un poco confuso. Ya sea que use varias transacciones cortas o una transacción masiva, el volumen total de registros de rehacer generados será el mismo. Las operaciones de E / S solo se producen cuando el búfer de registro de rehacer se escribe en el disco (dejando solo los puntos de verificación de la memoria caché del búfer por ahora), lo que ocurre al confirmar o cuando el búfer de rehacer está casi lleno. Posteriormente, si se compromete con frecuencia, causa E / S adicionales, por lo que me pregunto cómo eso puede reducir las E / S.
mustaccio

44
Es posible que desee leer lo que Tom Kyte tiene que decir sobre "compromisos frecuentes": asktom.oracle.com/pls/apex/… " está mal, mal, mal. Muy mal ... Muy mal "
a_horse_with_no_name
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.