2009-07-29 30 views
6

Quiero insertar n registros en una sola tabla. Puede haber muchos usuarios simultáneos y pueden insertar/actualizar/seleccionar datos de esta tabla. ¿Qué es la mejor manera de insertar en una tabla de este tipo SAY 1000 registros:Sql insertar rendimiento de consulta

  1. enviar una sola consulta SQL a una base de datos con múltiples inserciones. Esto ahorra llamadas de servidor a base de datos, pero (no estoy seguro) bloquea la tabla hasta que finalice la inserción y todas las demás consultas a esta tabla esperarán.
  2. Divide 1000 registros en algunos fragmentos y envíalos en múltiples consultas sql. Esto permite que las otras consultas se ejecuten en la tabla, pero pasen tiempo en el servidor para las llamadas a la base de datos.

¿Es esto depende de algo, o hay una sola manera que es siempre la óptima? ¿Esto depende de si se usan transacciones o no, al insertar datos? ¿Hay otras formas mejores de realizar una inserción de este tipo?

La base de datos que uso es MS SQL, pero es interesante cómo funciona en otras bases de datos como Oracle.

Respuesta

6

Esto depende totalmente de qué RDBMS esté usando.

En Oracle, escribe nunca lee en bloque, es por eso que puede guardar todos sus datos de una vez. Sin embargo, tenga en cuenta que esto disminuirá el rendimiento, ya que las consultas concurrentes necesitarán recuperar los datos del espacio de tabla UNDO que requerirán lecturas adicionales.

En SQL Server escrituras hacen bloque lee en filas/páginas/tablas afectadas (en función de cuestiones extensión de bloqueo), a menos que establezca TRANSACTION ISOLATION LEVEL-SNAPSHOT.

En todos los motores transaccionales que permiten escritura y lectura simultáneas, el motor necesita almacenar datos viejos y nuevos en alguna parte para que estén disponibles al mismo tiempo.

En Oracle, los datos antiguos se copian en el espacio de tabla UNDO.

En SQL Server, que se copia en tempdb (sólo cuando está activado SNAPSHOT aislamiento, de lo contrario es simplemente bloqueado).

Esto siempre requiere algunos recursos (memoria o disco), y puede quedarse sin estos recursos si su consulta UPDATE afecta a muchas filas.

1

Establezca un nivel de aislamiento (simultaneidad) que permita lecturas de los datos anteriores durante una transacción, p. Ej. SQL Server 2005+ tiene READ SNAPSHOT.

2

He escrito sobre este a while ago - Creo que la publicación responde algunas de sus preguntas. El asesoramiento de CK es sólido (y también lo es Quassno, tiene algunos puntos buenos sobre Oracle) si le preocupa que los lectores bloqueen a los escritores.

+0

publicación de blog interesante +1. Me interesa mi interés en cuanto a las transacciones de _suena_ aparecen más rápido en su prueba. Sospecho que es porque muchos de los bloqueos necesarios ya han sido tomados por pases previos. La única cosa crucial, sin embargo, que su publicación no aborda es el comportamiento bajo carga. Sus pruebas parecen estar en aislamiento; en un sistema en vivo, sospecho que los resultados se invertirían bastante rápido. – EBarr

2

La regla general es que debe dejar que la base de datos descubra cómo hacer el trabajo. Eso funciona mejor cuanto más le diga que haga en una declaración, es decir, debe insertar los 1000 registros de una vez. Esto funcionará mejor para la mayoría de los servidores de base de datos y la mayoría de los servidores no bloquean las lecturas para escrituras.

Existen excepciones: si la inserción es lenta porque el servidor es lento o la tabla grande o complicada, puede ser mejor dividir la consulta en grupos de pequeños insertos.

Un método intermedio sería enviar múltiples comandos de inserción para digamos 10 o 100 filas con commits en medio en un script grande al servidor.

Agregado: La mayoría de los servidores de bases de datos no bloquean la lectura como en Oracle, IBM DB/2 y MySQl usando tablas InnoDB. SQL Server, por otro lado, logra bloquear tablas incluso para lecturas y no está entre ellas.

+1

Creo que encontrarás que la mayoría de los DB tienen problemas donde los lectores bloquean a los escritores (Oracle no). – RichardOD

+0

La referencia de núcleo de Microsoft ADO.NET recomienda utilizar tamaños de lote de entre 100 y 1000. – RichardOD

+0

@RichardOD: ¿Puede publicar un enlace a esta recomendación? – Kamarey