2011-01-10 19 views
5

Dado: SQL Server 2008 R2. Salga de algunos discos de datos speedin. Log los discos rezagados.Optimización del rendimiento de inserción masiva ...?

Requerido: LOTES LOTES LOTES de insertos. Como 10.000 a 30.000 filas en una tabla simple con dos índices por segundo. Los insertos tienen un orden intrínseco y no se repetirán, ya que dicho orden de inserciones no debe mantenerse a corto plazo (es decir, múltiples insertos paralelos son correctos).

Hasta ahora: acumulando datos en una cola. Regularmente (subproceso de subprocesamiento asincrónico) vaciar hasta 1024 entradas en un elemento de trabajo que se pone en cola. Threadpool (clase personalizada) tiene 32 hilos posibles. Abre 32 conexiones.

Problema: el rendimiento está desactivado por un factor de 300 ... solo se insertan entre 100 y 150 filas por segundo. El tiempo de espera de registro es de hasta 40% - 45% del tiempo de procesamiento (ms por segundo) en el servidor sql. La carga de la CPU del servidor es baja (4% a 5% o menos).

No utilizable: inserción a granel. Los datos se deben escribir en tiempo real como sea posible en el disco. Esto es más o menos un proceso archivl de datos que se ejecutan a través del sistema, pero hay consultas que necesitan acceso a los datos regularmente. Podría tratar de tirarlos al disco y usar la carga masiva de 1 a 2 veces por segundo ... probaré esto.

¿Alguien una idea inteligente? Mi siguiente paso es mover el registro a un conjunto de discos rápidos (128 gb ssd moderna) y ver qué sucede en ese momento. El aumento significativo en el rendimiento probablemente hará las cosas bastante diferentes. Pero incluso entonces ... la pregunta es si/qué es factible.

Por lo tanto, dispare las ideas inteligentes.

+3

¿alguna vez se obtiene una resolución final a esto? – Carth

Respuesta

4

Ok, anywering myself. Voy a darle una oportunidad a SqlBulkCopy, mezclando hasta 65536 entradas y descargándolas cada segundo de manera asíncrona. Informará sobre las ganancias.

+3

75,000 registros por segundo usando 3 hilos es el resultado. – TomTom

+0

Guau, eso es bastante impresionante, buen trabajo! –

3

Estoy pasando por el mismo problema aquí, así que voy a seguir los pasos que estoy tomando para mejorar mi rendimiento.

  • independiente el registro y el archivo DBF en diferentes conjuntos de husillo
  • Uso básico de recuperación
  • que no mencionaron ningún requisito de indexación aparte del hecho de que el orden de los insertos no es importante - en este los índices agrupados de casos en cualquier otra cosa que no sea una columna de identidad no se deben usar.
  • comience su escalado de concurrencia nuevamente desde 1 y cese cuando su rendimiento se aplana; cualquier cosa sobre esto probablemente perjudicará el rendimiento.
  • en lugar de colocar en el disco a bcp, y como está utilizando SQL Server 2008, considere la posibilidad de insertar varias filas a la vez; esta declaración inserta tres filas en una sola llamada SQL

    INSERT INTO valores de la tabla (1,2,3), (4,5,6), (7,8,9)

estaba completándose en ~ 500 inserciones distintas por segundo desde un solo hilo. Después de descartar la red y la CPU (0 tanto en el cliente como en el servidor), asumí que el disco io en el servidor era el culpable, sin embargo, al insertar en lotes de tres obtuve 1500 insertos por segundo que descartan el disco io.

Está claro que la biblioteca del cliente MS tiene un límite superior en ella (y una inmersión en el reflector muestra algún código de terminación asincrónica).

Por lotes de esta manera, esperando que se reciban x eventos antes de llamar a la inserción, me he insertado ahora en ~ 2700 inserciones por segundo desde una sola hebra que parece ser el límite superior para mi configuración.

Nota: si no llega un flujo constante de eventos en todo momento, puede considerar agregar un temporizador que vacíe sus inserciones después de un cierto período (para que vea el último evento del día)

1

Algunas sugerencias para aumentar el rendimiento de inserción:

  • aumentar ADO.NET BatchSize
  • Elija índice agrupado de la tabla de destino con prudencia, de manera que los insertos no darán lugar a divisiones de nodos de índice agrupado (por ejemplo AutoInc columna)
  • inserción en una tabla de montón temporal primero, y luego emitir una gran "insert-por-select" para empujar todo lo que los datos de la tabla puesta en escena en la tabla destino real
  • Aplicar SqlBulkCopy
  • Elija "a granel Conectado" modelo de recuperación instad de "completa" modelo de recuperación
  • lugar un bloqueo de tabla antes de insertar (si el escenario de negocio lo permite)

Tomado de Tips For Lightning-Fast Insert Performance On SqlServer

Cuestiones relacionadas