gpt4 book ai didi

c# - 为什么人们说 SqlDataReader.GetXXX(i) 比 SqlDataReader[i] 快?

转载 作者:行者123 更新时间:2023-11-30 20:06:53 25 4
gpt4 key购买 nike


更新:事实证明反射也不一定很慢。使用 Fasterflect (http://www.codeproject.com/Articles/38840/Fasterflect-a-fast-and-simple-API-for-Reflection-i)。它从字面上进行反射(我指的是最字面意义上的“字面意思”一词,而不是比喻,因为它经常被误用)快了 100 倍。

我的代码现在已经达到加载数据并将数据放入我的业务对象的速度,就像 sql server management studio 在表上执行 select * 一样快。


我刚刚运行了这段代码来检查表中的任何数据类型并使用适当的 Get 方法:

        foreach (var p in obj.Properties)
{
object value;
var i = fieldNumbers[p.Alias];

if (p.Type == "System.Nullable`1[System.Int16]") value = dr.GetSqlInt16(i);
else if (p.Type == "System.Nullable`1[System.Int32]") value = dr.GetSqlInt32(i);
else if (p.Type == "System.Nullable`1[System.Decimal]") value = dr.GetSqlDecimal(i);
else if (p.Type == "System.Nullable`1[System.Boolean]") value = dr.GetSqlBoolean(i);
else if (p.Type == "System.String") value = dr.GetSqlString(i);
else if (p.Type == "System.Nullable`1[System.DateTime]") value = dr.GetSqlDateTime(i);
}

还有这个:

            foreach (var p in obj.Properties)
{
object value;
var i = fieldNumbers[p.Alias];
value = dr[i];
}

第二个始终执行得更快。我对此感到惊讶,但这似乎是真的。谁能告诉我是否忽略了这里的某些内容,因为我看到有几个人声称使用 GetXXX 方法性能更好。我将其作为一个整体进行计时,也对单独的检索操作进行计时。我真的只是揭穿了一个神话吗?

编辑:经过更多测试后,我发现了一些问题。

1st - 使用将值返回到强类型变量中的 get 方法稍微快一点(我运行的测试大约快 8%),我在没有上面所有多余代码的情况下测试了它,所以没有调度或类似的东西......只是苹果对苹果。

但是请注意,我使用的是 GetSqlXXX 函数而不是 GetXXX 函数。这是因为后者不能用于空值。但是,前者返回类型如 SqlInt32 而不是 int?。虽然我的字段不是 SqlXXX,但它们是简单的可空类型,如 int?。我认为大多数人经常会遇到这种情况,这意味着除非您想在整个代码中开始使用 SqlTypes,否则您不会真正获得类型化方法的速度提升。

其次,我注意到检索空值似乎比您通常预期的要慢......但这当然只是我的看法。

编辑 2:对于 Doug McClean 和 TheEvilPenguin,我“只是”分支的时间如下:

        Stopwatch sw = new Stopwatch();
long time = 0;

while (dr.Read())
{
var obj = new O();
obj.Initializing = true;


sw.Restart();
foreach (var p in obj.Properties)
{
if (p.Type == "System.Nullable`1[System.Int16]") continue;
else if (p.Type == "System.Nullable`1[System.Int32]") continue;
else if (p.Type == "System.Nullable`1[System.Decimal]") continue;
else if (p.Type == "System.Nullable`1[System.Boolean]") continue;
else if (p.Type == "System.String") continue;
}
time += sw.ElapsedTicks;
}
sw.Stop();
MessageBox.Show(time.ToString());

我不得不在其中留下几行不特定于分支的行,但您可以看到我只是在分支周围添加时间。起初我以毫秒为单位完成,结果(大约 60k 条记录)为 1。显然每个周期小于一毫秒,所以我切换到滴答声,结果为 466472,小于 1 毫秒的一半(除非我得到我的小数位混淆了......如果我不在,请有人纠正我)。那么分支有多贵?不是。

实际上,这些结果看起来确实很小,所以如果我在测试中犯了错误,请有人纠正我,但无论哪种方式,分支都是您可以做的最便宜的事情之一。

最佳答案

这一切都取决于 ADO 提供程序,这个答案涉及 SQL Server ADO.NET 提供程序,又名 SqlClient

查看您的基准测试,它看起来无效。特别是您要将一堆字符串比较添加到组合中。

对于有效的微基准测试,GetXYZlittle 一点点,因为 GetValue 的开销稍微多一些,特别是:

  1. GetValue 将内容汇集到内部 SqlBuffer.Value 中,这是一个简单的 case 语句,它分派(dispatch)给 GetXYZ 分派(dispatch)的相同属性.

  2. GetValue 调用 SqlStatistics.StartTimerGetXYZ 调用则不会。

您可能可以 IL bake 一个稍快的 GetValue() 实现,我怀疑这是否值得。

以下微基准测试展示了性能差异:

// include Dapper from nuget
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Dapper;
using System.Diagnostics;

namespace ConsoleApplication16
{
class Program
{
static void Main(string[] args)
{
var cnn = new SqlConnection("Data Source=.;Initial Catalog=tempdb;Integrated Security=True");
cnn.Open();

cnn.Execute("create table #t(num int, str nvarchar(50))");

// 10 k records
cnn.Execute("insert #t values (@num, @str)",
Enumerable.Range(1, 10000).Select(i => new { num = i, str = Guid.NewGuid().ToString() }));

Stopwatch sw;

SqlCommand cmd = new SqlCommand("select * from #t");
cmd.Connection = cnn;

for (int i = 0; i < 10; i++)
{
sw = Stopwatch.StartNew();
using (var reader = cmd.ExecuteReader())
{
int num;
string str;
while (reader.Read())
{
num = reader.GetInt32(0);
str = reader.GetString(1);
}
}
Console.WriteLine("GetXYZ {0}", sw.ElapsedTicks);

sw = Stopwatch.StartNew();
using (var reader = cmd.ExecuteReader())
{
int num;
string str;
while (reader.Read())
{
num = (int)reader.GetValue(0);
str = (string)reader.GetValue(1);
}
}
Console.WriteLine("GetValue {0}", sw.ElapsedTicks);
}

Console.ReadKey();
}
}
}

结果:

GetXYZ 25094GetValue 27877GetXYZ 24226GetValue 25450...GetXYZ 24029GetValue 26571

GetValue 始终如此缓慢。在绝对最坏的情况下差 5%。

关于c# - 为什么人们说 SqlDataReader.GetXXX(i) 比 SqlDataReader[i] 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9221944/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com