2009-05-19 65 views
11

En el discussion acerca de múltiples filas se insertan en el oráculo dos enfoques se demostraron:Insertar varias filas en Oracle

Primero:

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE) 
      select 8000,0,'Multi 8000',1 from dual 
union all select 8001,0,'Multi 8001',1 from dual 

Segundo:

INSERT ALL 
    INTO t (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3') 
    INTO t (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3') 
    INTO t (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3') 
    . 
    . 
    . 
SELECT 1 FROM DUAL; 

¿Alguien podría argumentar la preferencia de usar uno sobre otro?

P.S. No hice ninguna investigación yo mismo (incluso el plan de explicación), por lo que cualquier información u opinión sería apreciada.

Gracias.

Respuesta

2

La declaración que utiliza el UNION ALL tiene teóricamente una pequeña desventaja de rendimiento ya que tiene que unir los resultados de todas las declaraciones antes de que el inserto pueda suceder. El INSERT ALL no tiene esta desventaja, ya que el resultado final ya puede procesarse línea por línea.

Pero prácticamente el optimizador dentro de Oracle debe hacer la diferencia insignificante y depende de sus preferencias, de la forma que elija.

En mi opinión, el INSERT ALL es el mejor legible por humanos de los dos, mientras que la variante UNION ALL es la que ocupa menos espacio cuando se genera automáticamente.

+0

De acuerdo con la conclusión, pero: Nitpick: estas instrucciones INSERT no devuelven ningún valor, por lo que no tiene sentido decir que algo sucede "antes de que la inserción pueda suceder" o "línea por línea". De todos modos, él está usando UNION TODO para que no haya ningún problema, si eso es lo que estabas pensando. –

+1

Un rápido "plan de explicación" muestra que INSERTAR TODO con 4 líneas int SCOTT.EMP tiene un costo de 2 (1 inserción de varias tablas con el único costo de CPU en la doble selección) mientras que la variante UNION ALL tiene un costo de 8 (con cada SELECT causando otros 2). No es la ordenación sino la combinación de los resultados y los selectores únicos (al menos FAST DUAL) que están causando el costo. – Kosi2801

3

Sospecho que la solución 1 es un poco un truco que funciona y es probablemente menos eficiente que la alternativa diseñada de Insertar TODO.

Insertar todo es realmente diseñado para que usted inserte el número de filas en más de 1 mesa como resultado de una selección, por ejemplo:

Insert ALL 
into 
    t1 (c1, c2) values (q1, q2) 
    t2 (x1, x2) values (q1, q3) 
select q1, q2, q3 from t3 

Si desea cargar miles de filas y no está en la base de datos ya es, no creo que esta sea la mejor manera de hacerlo: si sus datos están en un archivo, quiere ver tablas externas o SQL Loader para insertar las filas de manera eficiente.

7

Desde el punto de vista del rendimiento, estas consultas son idénticas.

UNION ALL no dañará el rendimiento, ya que Oracle estima la consulta de UNION 'ed solo cuando lo necesita, no almacena en caché primero los resultados.

SELECT La sintaxis es más flexible en el sentido de que puede simplificar más fácilmente la consulta SELECT si desea cambiar algo.

Por ejemplo, la siguiente consulta:

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE) 
      select 8000,0,'Multi 8000',1 from dual 
union all select 8001,0,'Multi 8001',1 from dual 

puede reescribirse como

INSERT 
INTO pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE) 
SELECT 7999 + level, 0, 'Multi ' || 7999 + level, 1 
FROM dual 
CONNECT BY 
     level <= 2 

Al reemplazar 2 con número apropiado, puede obtener cualquier número de filas que desea.

En el caso de INSERT ALL, tendría que duplicar la descripción de la tabla de destino, que es menos legible si necesita, por ejemplo, 40 filas.

+1

Tenga en cuenta que al usar 'SOME_SEQUENCE.NEXTVAL' como valor, se obtiene un error de Oracle ** ORA-02287: el número de secuencia no se permite aquí ** (Oracle 11g). Aquí se describe una solución alternativa: http://www.orafaq.com/forum/t/54217/2/ - intente con 'INSERT INTO ... SELECT SOME_SEQUENCE.NEXTVAL, T. * FROM (SELECT ... UNION ALL SELECT. ..) T' –

3

El método INSERT ALL tiene un problema al insertar una mayor cantidad de filas en una tabla.

Hace poco quise insertar 1130 filas en una tabla con una única instrucción de SQL. Cuando traté de hacer esto con INSERT ALL método Tengo el siguiente error:

ORA-24335 - cannot support more than 1000 columns

Cuando solía INSERT INTO .. UNION ALL .. enfoque de todo fue bien.

Btw. No sabía sobre el método UNION ALL antes de encontrar esta discusión :)

2

he intentado alguna prueba y la solución debe ser más rápido

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE) 
      select 8000,0,'Multi 8000',1 from dual 
union all select 8001,0,'Multi 8001',1 from dual 

de amortiguación entre 300 < -> 400 filas (i intentado con odbc, este valor podría depender de su configuración)

-2

Debería considerar Array-Insert.

  • Fácil SQL
  • necesita algo de código del lado del cliente para configurar la matriz de parámetros-

Ésta es la manera de minimizar la Red-Tráfico si algunos cientos de inserciones que hay que hacer en un lote .

-1

Si tiene instrucciones de inserción que son más de 1000, coloque todas las instrucciones de inserción en un archivo .sql y ábralo en Toad o SQL Developer y luego ejecútelo. Todos los registros se insertarán.

+0

OP quería saber si uno de los enfoques que mencionó es preferible sobre el otro, no se trata de cómo/dónde ejecutar el SQL. – dlatikay

Cuestiones relacionadas