【发布时间】:2011-11-06 21:34:31
【问题描述】:
我一直在尝试尽可能快地从 SQL 服务器读取数据的方法,并且发现了一个有趣的发现。如果我将数据读入List<object[]> 而不是List<string[]>,性能会提高一倍以上。
我怀疑这是因为不必在字段上调用ToString() 方法,但我一直认为使用对象会对性能产生负面影响。
是否有任何理由不使用对象数组列表而不是字符串数组?
编辑:我刚刚想到的是这些数据的存储大小。将数据存储在对象数组中会比字符串占用更多空间吗?
这是我的测试代码:
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();
}
}
结果:
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
【问题讨论】:
-
无法与结果争论。您还应该将您的阅读器(和命令)也包含在 using 语句中,因为它们会泄漏内存。
-
测试肯定有问题...相比从数据库读取数据,使得字符串类型检查应该可以忽略不计。
-
出于好奇,如果您只是将 reader 值转换为字符串 (
row[i] = (string)reader[i];) 而不是在其上调用ToString(),或者使用内置的 @987654328,这有什么不同吗? @方法来检索值(row[i] = reader.GetString(i);)? (A假设所有列值都是字符串。) -
@Guffa 并没有说明这只是类型检查;这很可能是从其他数据类型到格式化形式的转换。毫无疑问,这会增加工作量。
-
@Guaffa - 正如 Marc 所说,正是从非字符串类型的转换导致了问题 - 当我使用 reader[i] 作为字符串时,我注意到与 object[] 测试的性能相似。
标签: c# performance sqldatareader