AdoNet vs LinqToSql vs NIntegrateQuery查询性能测试.
先上测试结果:
AdoNetTest: 267ms
AdoNetCachedCommandTest: 182ms
LinqToSqlTest: 3191ms
LinqToSqlCompiledQueryTest: 386ms
NIntegrateQueryTest: 266ms
AdoNet vs LinqToSql vs NIntegrateQuery查询性能测试.
先上测试结果:
AdoNetTest: 267ms
AdoNetCachedCommandTest: 182ms
LinqToSqlTest: 3191ms
LinqToSqlCompiledQueryTest: 386ms
NIntegrateQueryTest: 266ms
下载
下载测试数据库:AdventureWorksLT2008
下载测试代码:NIntegrateQueryPerformanceComparison.zip
代码导航

AdoNetTest.cs
1
class AdoNetTest : ITest
2
{
3
private static readonly string _connString = ConfigurationManager.ConnectionStrings[Constants.ConnectingStringName].ConnectionString;
4
5
private void DoExecute(int repeatTime)
6
{
7
for (var i = 1; i <= repeatTime; ++i)
8
{
9
using (var conn = new SqlConnection(_connString))
10
{
11
if (conn.State != System.Data.ConnectionState.Open)
12
conn.Open();
13
var cmd = new SqlCommand(
14
"SELECT TOP 1 ProductID,Name FROM SalesLT.Product WHERE ProductID = @ProductID", conn)
15
{CommandType = System.Data.CommandType.Text};
16
cmd.Parameters.Add(new SqlParameter("@ProductID", i));
17
using (var reader = cmd.ExecuteReader())
18
{
19
if (reader.Read())
20
{
21
var product = new Product
22
{
23
ProductID = ((int) reader["ProductID"]),
24
Name = ((string) reader["Name"])
25
};
26
}
27
}
28
}
29
}
30
}
31
32
ITest Members#region ITest Members
33
34
public void Prepare()
35
{
36
DoExecute(1);
37
}
38
39
public void Execute()
40
{
41
DoExecute(Constants.RepeatTime);
42
}
43
44
#endregion
45
}
46

AdoNetCachedCommandTest.cs
1
class AdoNetCachedCommandTest : ITest
2
{
3
private static readonly string _connString = ConfigurationManager.ConnectionStrings[Constants.ConnectingStringName].ConnectionString;
4
private static SqlCommand _cachedCommand;
5
private static SqlCommand GetCachedCommand()
6
{
7
if (_cachedCommand == null)
8
{
9
_cachedCommand = new SqlCommand(
10
"SELECT TOP 1 ProductID,Name FROM SalesLT.Product WHERE ProductID = @ProductID")
11
{CommandType = System.Data.CommandType.Text};
12
_cachedCommand.Parameters.Add(new SqlParameter("@ProductID", 0));
13
}
14
15
return _cachedCommand.Clone();
16
}
17
18
private void DoExecute(int repeatTime)
19
{
20
for (var i = 1; i <= repeatTime; ++i)
21
{
22
using (var conn = new SqlConnection(_connString))
23
{
24
if (conn.State != System.Data.ConnectionState.Open)
25
conn.Open();
26
var cmd = GetCachedCommand();
27
cmd.Parameters[0].Value = i;
28
cmd.Connection = conn;
29
30
using (var reader = cmd.ExecuteReader())
31
{
32
if (reader.Read())
33
{
34
var product = new Product
35
{
36
ProductID = ((int) reader["ProductID"]),
37
Name = ((string) reader["Name"])
38
};
39
}
40
}
41
}
42
}
43
}
44
45
ITest Members#region ITest Members
46
47
public void Prepare()
48
{
49
DoExecute(1);
50
}
51
52
public void Execute()
53
{
54
DoExecute(Constants.RepeatTime);
55
}
56
57
#endregion
58
}
59

LinqToSqlTest.cs
1
class LinqToSqlTest : ITest
2
{
3
private static readonly string _connString = ConfigurationManager.ConnectionStrings[Constants.ConnectingStringName].ConnectionString;
4
5
private void DoExecute(int repeatTime)
6
{
7
for (var i = 1; i <= repeatTime; ++i)
8
{
9
using (var conn = new SqlConnection(_connString))
10
{
11
if (conn.State != System.Data.ConnectionState.Open)
12
conn.Open();
13
14
var ctx = new AdventureWorksDataContext(conn);
15
var product = ctx.Products.SingleOrDefault(p => p.ProductID == i);
16
}
17
}
18
}
19
20
ITest Members#region ITest Members
21
22
public void Prepare()
23
{
24
DoExecute(1);
25
}
26
27
public void Execute()
28
{
29
DoExecute(Constants.RepeatTime);
30
}
31
32
#endregion
33
}
34

LinqToSqlCompiledQueryTest.cs
1
class LinqToSqlCompiledQueryTest : ITest
2
{
3
private static readonly string _connString = ConfigurationManager.ConnectionStrings[Constants.ConnectingStringName].ConnectionString;
4
5
private void DoExecute(int repeatTime)
6
{
7
var query = CompiledQuery.Compile((AdventureWorksDataContext ctx, int index)
8
=> ctx.Products.SingleOrDefault(p => p.ProductID == index));
9
10
for (var i = 1; i <= repeatTime; ++i)
11
{
12
using (var conn = new SqlConnection(_connString))
13
{
14
if (conn.State != System.Data.ConnectionState.Open)
15
conn.Open();
16
17
var ctx = new AdventureWorksDataContext(conn);
18
var product = query(ctx, i);
19
}
20
}
21
}
22
23
ITest Members#region ITest Members
24
25
public void Prepare()
26
{
27
DoExecute(1);
28
}
29
30
public void Execute()
31
{
32
DoExecute(Constants.RepeatTime);
33
}
34
35
#endregion
36
}
37

NIntegrateQueryTest.cs
1
class NIntegrateQueryTest : ITest
2
{
3
private static readonly string _connString = ConfigurationManager.ConnectionStrings[Constants.ConnectingStringName].ConnectionString;
4
5
private void DoExecute(int repeatTime)
6
{
7
for (var i = 1; i <= repeatTime; ++i)
8
{
9
var criteria = new ProductCriteria();
10
var cmd = new QueryCommandFactory(criteria.And(criteria.ProductID == i))
11
.GetQueryCommand();
12
cmd.Parameters.Add(new SqlParameter("@ProductID", i));
13
cmd.Connection.Open();
14
using (var reader = cmd.ExecuteReader())
15
{
16
if (reader.Read())
17
{
18
var product = new Product
19
{
20
ProductID = ((int) reader["ProductID"]),
21
Name = ((string) reader["Name"])
22
};
23
}
24
cmd.Connection.Close();
25
}
26
}
27
}
28
29
ITest Members#region ITest Members
30
31
public void Prepare()
32
{
33
DoExecute(1);
34
}
35
36
public void Execute()
37
{
38
DoExecute(Constants.RepeatTime);
39
}
40
41
#endregion
42
}
43
测试结果分析
- 在不使用CompiledQuery的情况下,LinqToSql的性能比AdoNet差一个数量级,用百分比的话就是慢超过1000%;
- 在缓存Command的情况下,AdoNet的查询性能可以提高约30%;
- 在使用CompiledQuery的情况下,LinqToSql的查询性能比缓存Command的AdoNet下慢50%;
- NIntegrqateQuery的查询性能和不带缓存的AdoNet查询性能相当,比LinqToSqlCompiledQuery快约40%;
* 如对测试结果有任何异议,欢迎根跟贴友好讨论。
什么是NIntegrateQuery?
- NIntegrateQuery是Teddy最新开发的开源组件NIntegrate的一部分。
- NIntegrate是一个企业级系统集成开发框架。它的核心设计思想是,提供一个基于数据库集中化管理WCF服务配置信息和应用程序配置信息的方案,从而使得基于WCF的企业级SOA系统集成真正成为可能。
- NIntegrateQuery是一个类似Linq的强类型数据库查询语言。它的设计目标并不是ORM,也当然不是重新发明一个类似LinqToSql的轮子。它的设计目标是一个安全(完全防范SQL注入攻击)、高性能(参见测试结果),所有查询对象可以跨WCF、跨COM传递,并且支持动态查询条件、分页、排序的数据库查询语言。因为这个设计目标,它目前不支持,作为NIntegrate的一个组件,将来也没有计划支持类似LinqToSql提供的join、group by这样的查询。如果您要做这样的查询,标准的做法是先建一个View,再对View进行查询。
- 对于比较频繁的查询操作,虽然NIntegrateQuery本身的查询性能是非常好的,但是,如果可能,还是建议尽可能使用存储过程。
- 对于所有的写操作,虽然NIntegrateQuery提供了一个基于DataAdapter.Update的简单实现,但是,出于性能考虑,原则上,建议使用存储过程,当然,您也可以选择同时使用包括LinqToSql在内的任意其他ORM组件。
NIntegrateQuery支持的其它功能还包括:
- 混合支持多数据库、不同类型数据库的查询(正式版本将至少支持:SQL Server, Oracle, DB2和MySql)。
- 对不同的数据库,支持可扩展的,甚至是仅特定数据库支持的方法或语法。
- NIntegrate中包括了基于NIntegrateQuery的通用WCF查询服务的定义和默认实现,以及基于NIntegrateQuery和通用WCF查询服务的ASP.NET DataSource控件,方便进行数据绑定。
后记
这篇文章写完第一遍发布之前点预览时Firefox崩溃了,结果所有内容在Live Writer里老老实实重写了一遍,我哭~~~。为了避免同样的悲剧,我强烈建议您,千万不要在没有在其他地方备份前,在Firefox里点击FreeTextBox这个Rich Editor的“Preview”按钮。我是32bit Window Server 2008 + Firefox 3.0。切忌、切忌~~
//我是结尾符
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2005-06-07 IE浏览器的条件编译指令和微软的ajax实现