2012-06-19 10 views
15

Mi compañía está maldita por una asociación simbiótica que se ha convertido en parásita. Para obtener nuestros datos del parásito, tenemos que usar una conexión odbc dolorosamente lenta. Sin embargo, me di cuenta recientemente de que puedo obtener más rendimiento al ejecutar consultas en paralelo (incluso en la misma tabla).La forma más rápida de insertar en paralelo a una sola tabla

Hay una gran mesa en particular que quiero extraer datos desde y moverlo a nuestra tabla local. Al ejecutar consultas en paralelo, puedo obtener datos más rápidamente, pero también me imagino que esto podría causar problemas al tratar de escribir datos de múltiples consultas en la misma tabla a la vez.

¿Qué consejo me puede dar sobre cómo manejar mejor esta situación para que pueda aprovechar el aumento de la velocidad de uso de consultas en paralelo?

EDIT: Obtuve algunos comentarios excelentes aquí, pero creo que no estaba completamente claro sobre el hecho de que estoy extrayendo datos a través de un servidor vinculado (que usa los controladores odbc). En otras palabras, eso significa que puedo ejecutar las instrucciones INSERT normales y creo que eso proporcionaría un mejor rendimiento que SqlBulkCopy o BULK INSERT (en realidad, no creo que BULK INSERT sea siquiera una opción).

+0

Como sugirió, las escrituras paralelas probablemente no ayuden al rendimiento. Puede encontrar algunas respuestas aquí http://stackoverflow.com/questions/2861944/how-do-i-do-very-fast-inserts-to-sql-server-2008 –

+0

¿Está migrando los datos? Lo pregunto porque dijiste que movías los datos a las tablas locales. Además, ¿cómo haces esto en el código, por ejemplo, C# o como parte de un trabajo sql? –

+0

@mouters Sí, pero los nuevos datos no entran en nuestra base de datos, así que tendré que copiar todo lo nuevo sobre una base diaria. Hasta ahora lo he estado haciendo en sms a mano, pero la idea paralela se hará en C# si lo hago. Probablemente no vaya a hacer esto en paralelo b/c Obtuve todos los datos históricos ahora y realmente solo necesito configurar un trabajo sql para ejecutar y obtener nuevos datos todas las noches. Pero solo quería obtener algo de información sobre la idea b/c que podría tener para usarla en el futuro cercano en otras cosas. –

Respuesta

12

¿Ha leído Load 1TB in less than 1 hour?

  1. abrir tantos procesos de carga y cuando tenga las CPU disponibles. Si tiene 32 CPU, ejecute 32 cargas paralelas. Si tiene 8 CPU, ejecute 8 cargas paralelas .
  2. Si tiene control sobre la creación de sus archivos de entrada, configúrelos como de un tamaño que sea uniformemente divisible por el número de hilos de carga que desea ejecutar en paralelo. Además, asegúrese de que todos los registros pertenezcan a una partición si desea utilizar la estrategia de cambio de partición.
  3. Uso de inserción masiva en lugar de BCP Si está ejecutando el proceso en la máquina SQL Server.
  4. Utilice la partición de tablas para obtener otro 8-10%, pero solo si sus archivos de entrada están GARANTIZADOS para que coincidan con su función de partición, lo que significa que todos los registros en un archivo deben estar en la misma partición.
  5. Utilice TABLOCK para evitar el bloqueo de fila a la vez.
  6. Use filas por LOTE = 2500, o algo cerca de esto si son importación de múltiples flujos en una sola tabla.

Para SQL Server 2008, hay ciertas circunstancias en las que puede utilizar minimal logging for a standard INSERT SELECT:

SQL Server 2008 mejora los métodos que se puede manejar con un mínimo registro. Es compatible con sentencias INSERT SELECT mínimamente registradas. Además, al activar el indicador de seguimiento 610, SQL Server 2008 admite el registro mínimo frente a un árbol B no vacío para los nuevos intervalos de clave que causan asignaciones de páginas nuevas.

+0

Gracias, esto es bueno pero realmente no se aplica (aparte del # 1) a mi situación porque no estoy cargando datos de un archivo sino de un servidor vinculado a través de controladores odbc ... así que hago declaraciones de inserción basadas en conjuntos regulares de todas formas. Entonces, me pregunto cómo haría para hacer el equivalente de configurar ROWS PER BATCH en una declaración de inserción normal o si puedo. –

+0

¿Está usando SQL Server 2008 o superior? El registro mínimo en las sentencias INSERT SELECT estándar es compatible bajo ciertas circunstancias. – 8kb

3

Si lo que buscas para hacer esto en código C# es decir, existe la opción de utilizar SqlBulkCopy (en el espacio de nombres System.Data.SqlClient) y como este artículo sugiere su posible hacerlo en paralelo.

http://www.adathedev.co.uk/2011/01/sqlbulkcopy-to-sql-server-in-parallel.html

+0

Lo único malo de hacer algo a granel es que tendrás que reconstruir tus índices después, ya que los ignora en el inserto. – SQLMason

+0

Bueno, estaba pensando en usar C# para gestionar la paralelización. No creo que usar SqlBulkCopy sea más rápido que usar SqlCommand.ExecuteNonQuery() para emitir la misma instrucción de inserción basada en conjuntos que haría directamente desde SSMS, ¿o sí? Creo que una cosa que la gente sigue respondiendo es que esto no viene de un archivo plano ... Tengo acceso para ejecutar declaraciones de inserción regulares directamente en los datos de origen. –

+0

Supongo que cuando dice esto "la misma instrucción de inserción basada en conjunto" ¿quiere decir que puede hacer una unión de base de datos cruzada? ¿También está tratando de insertar en la fuente también, o simplemente quiere decir que tiene acceso de lectura/escritura a la base de datos de origen (pero es básicamente irrelevante con lo que intenta hacer aquí)? –

Cuestiones relacionadas