sql >> Base de Datos >  >> RDS >> Oracle

¿INSERT de 10 millones de consultas en menos de 10 minutos en Oracle?

Sé que otros han mencionado esto y no quiere escucharlo, pero use SQL*Loader o tablas externas. Mi tiempo medio de carga para tablas de aproximadamente el mismo ancho es de 12,57 segundos por poco más de 10 m de filas. Estas utilidades han sido diseñadas explícitamente para cargar datos en la base de datos rápidamente y son bastante buenas en eso. Esto puede generar algunas penalizaciones de tiempo adicionales según el formato de su archivo de entrada, pero hay bastantes opciones y rara vez he tenido que cambiar los archivos antes de cargarlos.

Si no está dispuesto a hacer esto, entonces no tiene que actualizar su hardware todavía; debe eliminar todos los posibles impedimentos para cargar esto rápidamente. Para enumerarlos, elimine:

  1. El índice
  2. El gatillo
  3. La secuencia
  4. La partición

Con todo esto, obliga a la base de datos a realizar más trabajo y, dado que lo hace de manera transaccional, no está utilizando la base de datos en todo su potencial.

Cargue los datos en una tabla separada, diga ABC_LOAD . Después de que los datos se hayan cargado por completo, realice un simple INSERTAR instrucción en ABC.

insert into abc
select abc_seq.nextval, a.*
  from abc_load a

Cuando haga esto (e incluso si no lo hace), asegúrese de que el tamaño de caché de secuencia sea correcto; para citar:

Cuando una aplicación accede a una secuencia en la caché de secuencias, los números de secuencia se leen rápidamente. Sin embargo, si una aplicación accede a una secuencia que no está en el caché, entonces la secuencia debe leerse desde el disco al caché antes de usar los números de secuencia.

Si sus aplicaciones usan muchas secuencias al mismo tiempo, es posible que su caché de secuencias no sea lo suficientemente grande para contener todas las secuencias. En este caso, el acceso a los números de secuencia a menudo puede requerir lecturas de disco. Para un acceso rápido a todas las secuencias, asegúrese de que su caché tenga suficientes entradas para contener todas las secuencias utilizadas simultáneamente por sus aplicaciones.

Esto significa que si tiene 10 subprocesos que escriben simultáneamente 500 registros cada uno usando esta secuencia, entonces necesita un tamaño de caché de 5000. El documento ALTER SEQUENCE indica cómo cambiar esto:

alter sequence abc_seq cache 5000

Si sigue mi sugerencia, aumentaría el tamaño de la memoria caché a alrededor de 10,5 m.

Considere el uso de la sugerencia APPEND (vea también Oracle Base); esto le indica a Oracle que use una inserción de ruta directa, que agrega datos directamente al final de la tabla en lugar de buscar espacio para colocarlos. No podrá usar esto si su tabla tiene índices, pero podría usarlo en ABC_LOAD

insert /*+ append */ into ABC (SSM_ID, invocation_id , calc_id, ... )
select 'c','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'a','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'b','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'c','g',NULL, 'test', 123 , 'N', 'asdf' from dual

Si usa la sugerencia APPEND; Agregaría TRUNCATE ABC_LOAD después de haber insertado en ABC de lo contrario, esta tabla crecerá indefinidamente. Esto debería ser seguro ya que habrás terminado de usar la mesa para entonces.

No mencionas qué versión o edición u Oracle estás usando. Hay una serie de pequeños trucos adicionales que puedes usar:

  • Oraculo 12c

    Esta versión admite columnas de identidad; podrías deshacerte de la secuencia por completo.

    CREATE TABLE ABC(
       seq_no         NUMBER GENERATED AS IDENTITY (increment by 5000)
    
  • Oráculo 11g r2

    Si mantienes el gatillo; puede asignar el valor de la secuencia directamente.

    :new.seq_no := ABC_seq.nextval;
    
  • Edición empresarial de Oracle

    Si está utilizando Oracle Enterprise, puede acelerar la INSERCIÓN desde ABC_LOAD usando la sugerencia PARALLEL:

    insert /*+ parallel */ into abc
    select abc_seq.nextval, a.*
      from abc_load a
    

    Esto puede causar sus propios problemas (demasiados procesos paralelos, etc.), así que pruebe. podría ayuda para las inserciones por lotes más pequeñas, pero es menos probable ya que perderá tiempo calculando qué subproceso debe procesar qué.

tl;dr

Utilice las utilidades que vienen con la base de datos.

Si no puede usarlos, deshágase de todo lo que pueda ralentizar la inserción y hágalo de forma masiva, porque para eso es buena la base de datos.