2010-09-16 26 views
37

Necesito cargar una columna de cadenas desde la tabla en SqlServer en Matriz en la memoria usando C#. ¿Existe una manera más rápida que abrir SqlDataReader y recorrerlo? La tabla es grande y el tiempo es crítico.¿Hay algo más rápido que SqlDataReader en .NET?

EDIT Estoy tratando de construir .dll y usarlo en el servidor para algunas operaciones en la base de datos. Pero es lento por ahora. Si esto es más rápido que tengo que rediseñar la base de datos. Es difícil que haya alguna solución para acelerar las cosas.

+0

No lo creo. –

Respuesta

49

Lector de datos

Sobre el acceso más rápido se llega a SQL es con el SqlDataReader.

perfil it

Vale la pena realmente perfiles donde su problema de rendimiento es. Usualmente, donde crees que el problema de rendimiento es, se ha demostrado que está totalmente mal después de haberlo perfilado.

Por ejemplo, podría ser:

  1. El tiempo de la consulta ... se necesita para ejecutar
  2. El tiempo ... la toma de datos para copiar todo el sitio limítrofe red/proceso
  3. El tiempo ... .Net tarda en cargar los datos en la memoria
  4. El tiempo ... el código necesario para hacer algo con él

de perfiles de cada uno de estos en Isola le dará una mejor idea de dónde está su cuello de botella.Para perfilar su código, hay una caché great article from Microsoft

que

Lo que hay que mirar para mejorar el rendimiento es trabajar si tiene que cargar todos los datos cada vez. ¿Se puede almacenar en caché la lista (o parte de ella)? Eche un vistazo al nuevo espacio de nombres System.Runtime.Caching.

reescritura como T-SQL

Si estás haciendo operaciones puramente de datos (como su pregunta sugiere), se podría reescribir el código que está utilizando los datos a ser T-SQL y ejecutar de forma nativa en SQL . Esto tiene el potencial de ser mucho más rápido, ya que trabajará directamente con los datos y no los cambiará.

Si su código tiene mucha lógica de procedimiento necesaria, puede intentar mezclar T-SQL con CLR Integration, ofreciéndole los beneficios de ambos mundos.

Esto se reduce a la complejidad (o más naturaleza de procedimiento) de su lógica.

Si todo lo demás falla

Si todas las áreas son óptimas (o lo más cerca), y su diseño es sin culpa. Ni siquiera entraría en la micro-optimización, solo me throw hardware at it.

¿Qué hardware? Pruebe el reliability and performance monitor para averiguar dónde está el cuello de la botella. Muy probablemente lugar para el problema que describe HDD o RAM.

+1

He probado algo, SqlDataReader es obviamente más rápido que DataSet;) Sí, el tiempo de carga está empeorando el rendimiento. – watbywbarif

+0

Y no estoy enviando al cliente, .dll se usa en la misma máquina que el servidor para algunos usos internos. – watbywbarif

+0

Editado para que coincida con su pregunta actualizada. – badbod99

7

Sospecho que SqlDataReader es casi tan buena como la que obtendrás.

+3

¡Ja! ¿Alguno de los downvoters se preocuparía por explicar qué pasa con esta respuesta? – LukeH

16

No. En realidad, no es la manera más rápida, es la ÚNICA (!) Forma. Todos los otros mecanismos INTERNAMENTE usan un DataReader de todos modos.

+0

Me había preguntado si ese era el caso. –

19

Si SqlDataReader no es lo suficientemente rápido, quizás deba almacenar sus cosas en otro lugar, como un caché (en memoria).

+0

De acuerdo: ¿puede cargar los datos por adelantado e iterar desde una colección en la memoria? – tomfanning

+1

+1 - una capa de almacenamiento en caché o en la base de datos de memoria es el camino a seguir. –

2

¿Qué tal transformar una columna de filas en una fila de columnas y tener solo una fila para leer? SqlDataReader tiene una optimización para leer una sola fila (System.Data.CommandBehavior.SingleRow argumento de ExecuteReader), por lo que tal vez puede mejorar la velocidad un poco.

veo varias ventajas:

  • mejora de fila única,
  • No hay necesidad de acceder a una gran variedad en cada iteración (reader[0]),
  • La clonación de un array (reader) a otro puede ser más rápido que recorrer los elementos y agregar cada uno a una nueva matriz.

Por otro lado, tiene la desventaja de obligar a la base de datos SQL a hacer más trabajo.

+0

Suena extraño, pero como este archivo .dll se usa en el servidor, parece que obtengo datos de forma óptima por SqlDataReader que construyendo una fila en SQL. – watbywbarif

1

"Proporciona una forma de leer una secuencia de solo reenvío de filas desde una base de datos de SQL Server" Este es el uso de SqlDataReader de MSDN. La estructura de datos detrás de SqlDataReder solo permite lectura hacia adelante, está optimizada para leer datos en una dirección. En mi opinión, quiero utilizar SqlDataReader que DataSet para la lectura de datos simple.

5

SqlDataReader es la manera más rápida. Asegúrese de utilizar los métodos ordinales get by en lugar de obtener por nombre de columna. p.ej. GetString (1);

También vale la pena experimentar con MinPoolSize en la cadena de conexión para que siempre haya algunas conexiones en la agrupación.

+0

¿Puede explicar más acerca de MinPoolSize, no veo cómo esto debería ayudar? – watbywbarif

+0

En .Net Las conexiones de base de datos se devuelven a un grupo de conexiones después de cerrarse y, finalmente, la conexión del servidor SQL subyacente se cierra después de un período de inactividad. Esto genera los eventos de inicio de sesión y cierre de sesión. En ciertos casos (llamadas de servicio web infrecuentes) puede ser beneficioso tener siempre listas conexiones en el grupo para manejar la primera solicitud rápidamente en lugar de tener que abrir una nueva conexión con el servidor SQL. – softveda

3

El SqlDataReader será la forma más rápida. Optimice el uso del mismo, utilizando el método Getxxx apropiado, que toma un ordinal como parámetro.

Si no es lo suficientemente rápido, vea si puede modificar su consulta. Coloque un índice de cobertura en la (s) columna (s) que desea recuperar. Al hacerlo, el servidor Sql solo tiene que leer el índice, y no tiene que ir directamente a la tabla para recuperar toda la información que se requiere.

+0

consulta es sólo una selección de columna, no hay lugar para la optimización de allí, sólo para rediseñar la base de datos;. ( – watbywbarif

+0

@watbywbarif un índice todavía le ayudará incluso en una sola columna seleccionar – msarchet

+0

he comprobado, que ya está indexada – watbywbarif

0

Si la capacidad de respuesta es un problema al cargar una gran cantidad de datos, consulte el uso de los métodos asincrónicos - BeginReader.

Lo uso todo el tiempo para rellenar elementos de GUI grandes en el fondo mientras la aplicación sigue siendo receptiva.

No ha dicho exactamente qué tan grande es esta información, o por qué la está cargando todo en una matriz.

Muchas veces, para grandes cantidades de datos, es posible que desee dejarlo en la base de datos o dejar que la base de datos haga el trabajo pesado. Pero tendríamos que saber qué tipo de procesamiento está haciendo que lo necesita todo en una matriz a la vez.

+0

La capacidad de respuesta no es un problema – watbywbarif

1

Usted tiene 4 conjuntos de los gastos generales - acceso al disco - .net código (CPU) - código del servidor SQL (CPU) - Tiempo para cambiar de código administrado y no administrado (CPU)

En primer lugar se

select * where column = “junk” 

lo suficientemente rápido para usted, si no la única solución es hacer que el disco sea más rápido. (Puede obtener datos de SQL Server más rápido de lo que puede leerlo)

Puede definir una función de servidor Sql en C# y luego ejecutar la función sobre la columna; lo siento, no sé cómo hacerlo. Esto puede ser más rápido que un lector de datos.

Si tiene más de una CPU y conoce un valor en el medio de la tabla, puede intentar usar más de un hilo.

Puede escribir algo de TSQL que combine todas las cadenas en una sola cadena usando un separador que sepa que es seguro. Luego divide la cuerda nuevamente en C#. Esto reducirá la cantidad de viajes de ida y vuelta entre códigos administrados y no administrados.

+0

No sé cómo se acelerarían más subprocesos de datos ya que SqlDataReader lee secuencialmente? – watbywbarif

+0

Cada subproceso podría utilizar su propio SqlDataReader, siempre que es posible que algo se puede estar en el "dónde" para definir los datos entre los hilos. –

+0

buena idea, tal vez puede ayudar. 1 – watbywbarif

1

Algunas cosas a nivel de la superficie a considerar que pueden afectar a la velocidad (además de una técnica de lector):

  1. base de datos de consulta Optimización
    • OrdenarPor es caro
    • distintos es caro
    • RowCount es costoso
    • GroupBy es costoso
    • e tc. A veces no puedes vivir sin estas cosas, pero si puedes manejar algunas de estas cosas en tu código C#, puede ser más rápido.
  2. la tabla de base de datos de indexación (para empezar, son los campos en la cláusula WHERE indexado?)
  3. DataTypes tabla de base de datos (¿Está utilizando los más pequeños posibles, teniendo en cuenta los datos?)
  4. ¿Por qué estás convirtiendo el lector de datos a una matriz?
    • por ejemplo, ¿le serviría igual de bien crear un adaptador/datatable que luego no necesitaría convertir a una matriz?
  5. ¿Has consultado Entity Framework? (podría ser más lento ... pero si no tiene opciones, podría valer la pena investigarlo solo para asegurarse)

Sólo pensamientos aleatorios. No estoy seguro de qué podría ayudar en su situación.

+5

Ordenamiento, agrupamiento, etc., son más rápido de manejar en C# de en SQL? Eso no parece probable, pero m aybe sabes algo que yo no. –

Cuestiones relacionadas