2009-12-04 19 views
5

Nunca lo he intentado, así que no sé si me hubiera topado con problemas de memoria.SQL Server y SqlDataReader - Trillion Records - Memoria

¿Pero puede un SqlDataReader leer un billón de registros? Todo se transmite correctamente? Estoy un poco verde con lo que está haciendo el protocolo SQL/TDS bajo las sábanas.

ACTUALIZACIÓN Traducir Trillion a significar un número muy grande. Probablemente debería haber dicho algo así como mil millones o 100 millones.

+4

¿Está pensando en leer un billón de registros? o es solo por interés? – gbn

Respuesta

10

Sí, eso se transmitirá ... pero no creo que en realidad deba intentar hacerlo.

Si pudieras leer un millón de registros por segundo (lo cual me parece poco probable) todavía necesitarías 12 días para leer un billón de registros ... eso es mucho trabajo para arriesgarte a perder a la mitad.

Ahora te das cuenta probablemente no realmente quiere leer un billón de registros, literalmente, pero mi punto es que si se puede separar su "gran cantidad" de trabajo en lotes lógicos de todos modos, eso es probablemente una buena idea .

+0

Así que mi pregunta original iba a ser cuál es la mejor estrategia de procesamiento por lotes para ADO.NET y SQL Server ... así que ¿cuál es la mejor manera de abordar 1000 registros a la vez? Supongamos que está realizando una actividad de tipo MapReduce. Me doy cuenta de que hay otras herramientas para esto (abierto y comercial) pero si la empresa para la que trabajas no te deja usarlas ... no me hacen ningún bien. (excepto intentar tomar prestadas ideas de) – BuddyJoe

+0

Buen punto sobre los 12 días +1. Tal vez elegí un número demasiado alto. – BuddyJoe

+0

Para ser sincero, la mejor estrategia de procesamiento por lotes dependerá de la naturaleza exacta de la tarea. ¿Se puede dividir de manera confiable en lotes, incluso si las consultas se ejecutan en una fecha posterior? ¿Puedes dividirlo en lotes con anticipación y dar diferentes lotes a diferentes computadoras? ¿Hay algo más que escriba en estos datos? ¿Hay índices apropiados? Básicamente, se trata de encontrar la forma de dividir los datos de forma confiable y eficiente. –

1

Sí, puede tomar un tiempo (siempre que su SQL no esté haciendo nada tonto al intentar tomar una instantánea o algo), pero si su servidor puede transmitirlo, el SqlDataReader no debería tener un uso de memoria problema.

13

Hay algunos detalles.

  • SqlDataReader normalmente leer una fila entera en la memoria caché y él. Esto incluye cualquier campo BLOB, por lo que puede terminar el almacenamiento en memoria caché de varios campos de 2 GB en la memoria (XML, VARBINARY (MAX), VARCHAR (MAX), NVARCHAR (MAX)). Si dichos campos son una preocupación, debe pasar el CommandBehavior.SequentialAccess al ExecuteReader y usar las capacidades de transmisión de los tipos específicos de SqlClient como SqlBytes.Stream.

  • Una conexión está ocupada hasta que finalice el SqlDataReader. Esto crea problemas transaccionales porque no podrá hacer ningún procesamiento en la base de datos en la misma transaciton, porque la conexión está ocupada. Intentar abrir una conexión diferente e inscribirse en la misma transacción fracasará, ya que las transacitones distribuidas en bucle están prohibidas. La intención es usar MARS. Para hacerlo, configure MultipleActiveResultSets=True en la conexión. Esto le permite emitir un comando en la misma conexión mientras que un lector de datos todavía está activo (típico ciclo de búsqueda-proceso-recuperación). Lea el enlace a Christian Kleinerman con sumo cuidado, asegúrese de comprender los problemas y las restricciones en torno a MARS y las transacciones, son bastante sutiles y contradictorios.

  • El procesamiento prolongado en el cliente bloqueará el servidor. Su consulta seguirá ejecutándose todo este tiempo y el servidor tendrá que suspenderla cuando la tubería de comunicación se llene. Una consulta consume worker (o más si tiene planes paralelos) y los trabajos son muy producto básico en un servidor (se equiparan aproximadamente a los subprocesos). No será capaz de permitirse que muchos clientes procesen enormes conjuntos de resultados en su propio entorno.

  • Tamaño de la transacción. Procesar un trillón de registros en una transacción nunca va a funcionar. El registro tendrá que crecer para acomodar la transacción total y no truncará ni reutilizará los VLF, lo que da como resultado gran crecimiento del registro.

  • Tiempo de recuperación. Si el procesamiento falla en el registro 999 mil millones, tendrá que deshacer todo el trabajo realizado, por lo que tomará otros '12' días para deshacerse.

+0

Muy buena información. +1 ¿Qué papel juegan las transacciones en el sistema si los datos solo necesitan ser consistentes? ¿Cuál sugeriría es la forma correcta de procesar por lotes 1000 o 10000 a la vez? (vea los comentarios a Jon Skeet) – BuddyJoe

+0

La forma correcta de crear lotes que puedan reanudarse de manera segura depende de la tarea real que se realice. Un ejemplo trivial es tener una tabla con el valor clave actual en clúster. En una transacción, obtienes el valor de la tabla, seleccionas las siguientes 10k filas ordenadas por clave agrupada, las procesas, actualizas el valor clave actual en la tabla, confirma. Enjuague, ciclo y repita. –