Ho sperimentato modi di leggere dati da un server SQL il più rapidamente possibile e ho trovato una scoperta interessante. Se leggo i dati in un List<object[]>
anziché in un List<string[]>
, le prestazioni aumentano di oltre il doppio.Elenco prestazioni SqlDataReader <string[]> o Elenco <object[]>
Sospetto che ciò sia dovuto al fatto che non è necessario chiamare il metodo ToString()
nei campi, ma ho sempre pensato che l'utilizzo di oggetti avesse un impatto negativo sulle prestazioni.
C'è qualche motivo per non utilizzare un elenco di matrici di oggetti invece di matrici di stringhe?
EDIT: Un pensiero che ho avuto è stata la dimensione di archiviazione di questi dati. La memorizzazione dei dati negli array di oggetti richiede più spazio rispetto alle stringhe?
Ecco il mio codice di prova:
private void executeSqlObject()
{
List<object[]> list = new List<object[]>();
using (SqlConnection cnn = new SqlConnection(_cnnString))
{
cnn.Open();
SqlCommand cmd = new SqlCommand("select * from test_table", cnn);
SqlDataReader reader = cmd.ExecuteReader();
int fieldCount = reader.FieldCount;
while (reader.Read())
{
object[] row = new object[fieldCount];
for (int i = 0; i < fieldCount; i++)
{
row[i] = reader[i];
}
list.Add(row);
}
}
}
private void executeSqlString()
{
List<string[]> list = new List<string[]>();
using (SqlConnection cnn = new SqlConnection(_cnnString))
{
cnn.Open();
SqlCommand cmd = new SqlCommand("select * from test_table", cnn);
SqlDataReader reader = cmd.ExecuteReader();
int fieldCount = reader.FieldCount;
while (reader.Read())
{
string[] row = new string[fieldCount];
for (int i = 0; i < fieldCount; i++)
{
row[i] = reader[i].ToString();
}
list.Add(row);
}
}
}
private void runTests()
{
Stopwatch watch = new Stopwatch();
for (int i = 0; i < 10; i++)
{
watch.Start();
executeSqlObject();
Debug.WriteLine("Object Time: " + watch.ElapsedMilliseconds.ToString());
watch.Reset();
}
for (int i = 0; i < 10; i++)
{
watch.Start();
executeSqlString();
Debug.WriteLine("String Time: " + watch.ElapsedMilliseconds.ToString());
watch.Reset();
}
}
E i risultati:
Object Time: 879
Object Time: 812
Object Time: 825
Object Time: 882
Object Time: 880
Object Time: 905
Object Time: 815
Object Time: 799
Object Time: 823
Object Time: 817
Average: 844
String Time: 1819
String Time: 1790
String Time: 1787
String Time: 1856
String Time: 1795
String Time: 1731
String Time: 1792
String Time: 1799
String Time: 1762
String Time: 1869
Average: 1800
Non posso discutere con i risultati. Dovresti anche avvolgere i tuoi lettori (e anche i comandi) nell'uso delle istruzioni perché possono perdere memoria. –
Ci deve essere qualcosa di sbagliato nel test ... Rispetto alla lettura dei dati dal database, fare in modo che il tipo di stringa check * dovrebbe * essere trascurabile. – Guffa
Per curiosità, è diverso se si lancia semplicemente il valore del lettore su una stringa ('row [i] = (string) reader [i];') invece di chiamare 'ToString()' su di esso, o invece, usando il built-in 'SqlDataReader.GetString()' metodo per recuperare il valore ('row [i] = reader.GetString (i);')? (Aassumendo tutti i valori di colonna sono stringhe.) –