我正在寻找从 SQL Server 获取 long 列表的最快方法。
据我所知,下面的代码是您通常可以运行的最快的代码,而减慢它的是 dr.Read() 中发生的所有事情,以及在某种程度上为每一行调用 dr.GetInt64。
var ids = new long[count];
using (var dr = new SqlCommand(string.Format(@"SELECT TOP 10000 ID FROM Data", count),
conn).ExecuteReader(CommandBehavior.SequentialAccess))
{
while (dr.Read())
{
ids[i++] = dr.GetInt64(0);
}
}
查询花费的时间可以忽略不计,因此时间花在数据阅读器中的解析和类型验证上。对于 100,000 条记录,大约需要 25 毫秒,这与迭代数组中的 100,000 个项目所需的 0.20 毫秒相比非常慢。
因为我只要求一个 long 列表,所以我想知道是否可以将它们作为单字节数组获取。我所追求的是这样的:
var bytes = (byte[]) new SqlCommand("(I don't know)", conn).ExecuteScalar();
Buffer.BlockCopy(bytes, 0, ids, 0, 10000);
这将大大减少解析时间。
有人可以告诉我这种方法是否可行吗?
更新:
至少这些方法并不快:
CLR 聚合
可以定义用 .NET 编写的自定义聚合函数。我试图制作一个非常简单的,什么都不做的(使用 SqlUserDefinedAggregate(Format.Native) 使其尽可能快)。这将查询时间增加到 60 毫秒,因此它永远不会更快。
查询如下:
SELECT dbo.ByteIt(ID) FROM (SELECT TOP 100000 ID FROM Data) T
连接 varbinary(max)
可以使用纯 SQL 构建字节数组。那很慢。
DECLARE @n varbinary(max)
SET @n = 0;
SELECT TOP 10000 @n = @n + cast(id as varbinary(8)) FROM Data;
SELECT @n;
为什么它可能永远不值得付出努力
我能想到的最快的原生聚合是 COUNT。
SELECT COUNT(ID) FROM (SELECT TOP 100000 ID FROM Data) T
这需要 10 毫秒,并且必须是考虑每个值的任何方法的绝对下限。我认为这种性能提升并不值得付出努力。
可悲的是,我认为我的问题的答案是“可以完成但不能更快。与 25 毫秒一起生活”。