.net - recorrer - DataTable.Select vs DataTable.rows.Find vs foreach vs Find(Predicado<T>)/Lambda
jquery datatable recorrer rows (5)
Tengo una DataTable / colección que está en caché en la memoria, quiero usar esto como fuente para generar resultados para un cuadro de texto de autocompletado (usando AJAX, por supuesto). Estoy evaluando varias opciones para obtener los datos rápidamente. El número de elementos en la colección / filas en el datatable puede variar de 10000 a 2,000,000. (Para que no nos desviemos, por el momento supongamos que se ha tomado la decisión, tengo suficiente memoria RAM y usaré el caché y no la consulta de la base de datos para esto)
Tengo un poco de lógica de negocios adicional para este procesamiento; Tengo que priorizar la lista de autocompletado según una columna de priority
(int) en la colección. Entonces, si alguien busca Micro
y obtengo 20 resultados de palabras / oraciones que comienzan con Micro
, elegiré los 10 elementos principales con mayor prioridad. (de ahí la necesidad de tener una propiedad de prioridad asociada con el valor de la cadena).
Los elementos de la colección ya están ordenados alfabéticamente.
¿Cuál sería la mejor solución en este caso?
1. Usando DataTable. Seleccione (.
2. Usando DataTable.Rows.Find ( .
3. Utilice una colección personalizada con foreach o para iterar a través de sus valores.
4. Utilice una colección genérica con delegados anónimos o lambda (¿ ya que ambos dan el mismo rendimiento o not ?)
¿Qué pasa con un DataView? Puede aplicar su condición de filtro Y ordenar por prioridad, e iterar fácilmente a través de los resultados para agregar a sus resultados.
En mi autocomplete
, probé primero el enfoque linq/lambda
, el rendimiento es un poco lento. DataTable.Select
es más rápido que linq
, así que uso esto. Todavía no he comparado el rendimiento entre datatable.Select
y datatable.Find
Los gráficos no están publicados en mi entrada de blog; se pueden encontrar más detalles en http://msdn.microsoft.com/en-us/library/dd364983.aspx
Otra cosa que he descubierto desde entonces es que, para grandes conjuntos de datos, el uso de un diccionario genérico encadenado funciona increíblemente bien. También ayuda a aliviar muchos de los problemas causados por las operaciones de clasificación requeridas para las operaciones de agregación, como mín y máx (ya sea con DataTable.Compute
o LINQ
).
Por "diccionario genérico encadenado" me refiero a un Dictionary(Of String, Dictionary(Of String, Dictionary(Of Integer, List(Of DataRow))))
o técnica similar, donde la clave de cada diccionario es un término de búsqueda.
Por supuesto, esto no será útil en todas las circunstancias, pero tengo al menos un escenario en el que la implementación de este enfoque lleva a una mejora del rendimiento de 500x
.
En su caso, consideraría usar un diccionario simple con los primeros 1-5 caracteres, luego una List(Of String)
. Tendría que crear este diccionario una vez, agregando las palabras a las listas con los primeros 1-5 caracteres, pero después podrá obtener resultados increíblemente rápidos.
Generalmente envuelvo cosas como esta en una clase que me permite hacer cosas como agregar palabras fácilmente. También es posible que desee utilizar una lista SortedList(Of String)
para ordenar los resultados automáticamente. De esta manera, puede buscar rápidamente la lista de palabras que coinciden con los primeros N caracteres que se han escrito.
Podríamos especular sobre ello todo el día, pero ya que este no es un gran código, ¿por qué no escribir cada uno y compararlos entre sí?
public delegate void TestProcedure();
public TimeSpan Benchmark(TestProcedure tp)
{
int testBatchSize = 5;
List<TimeSpan> results = new List<TimeSpan>();
for(int i = 0; i<testBatchSize; i++)
{
DateTime start = DateTime.Now;
tp();
results.Add(DateTime.Now - start);
}
return results.Min();
}
según el siguiente blog
http://blog.dotnetspeech.net/archive/2008/08/26/performance----datatable.select-vs-dictionary.aspx
DataTable.Rows.Find es mucho, mucho más rápido que DataTable.Select.