OleDB和SQLClient有哪些优缺点?

19

一些背景信息:我正在处理的系统之一是一个 .NET 2.0 Web 应用程序。前端使用 VB.NET,后端使用 SQL Server 2005。基于各种原因,现已无从考证的设计者决定使用 .NET OleDB 连接而非 SQLClient 连接。

几年的开发之后,这个特定系统即将从 "beta" 阶段迈入 "1.0" 阶段。在这一点上,我们谈论的一个问题是转向使用 SQLClient 连接。虽然我知道使用它是最佳实践,并且这是访问 SQL Server 2005 更高级特性的唯一方式(显然我们没有使用),但使用其中一个的优点是什么?有没有任何隐藏的要注意的问题?还有人可以指引我查看一些相对速度的基准测试结果吗?(我听说 SQLClient 应该更快,但我从未见过任何数据来支持这一点。)

感谢大家。

5个回答

25

OleDb更通用。如果你将来换到不同类型的数据库,很有可能会有一个Ole驱动程序,你就不必改变太多代码。

另一方面,Sql Server本地驱动程序应该更快,就像你所说的,并且它具有更好的参数支持(参数可以使用名称,不必按顺序)。

根据我的个人经验,我从未注意到速度差异;我也找不到任何支持这种说法的东西。我怀疑性能优势是真实的,但你必须处理数百万条记录才能开始测量它。

我注意到有意义的区别是错误消息。我在旧的OleDb应用程序中遇到了问题,因绝望而将其切换到SqlClient。当然,它仍然无法正常工作,但更好的错误消息提供了足够的新信息,让我能够解决问题。


3
值得注意的是,考虑到我前两句话,微软现在正在弃用Ole而转向使用Odbc。 - Joel Coehoorn

14

OLEDB的速度比SQLClient快得多,除非通过ADO.NET访问它。OLEDB驱动程序是使用本机非托管代码编写的,但是,当您通过ADO.NET访问这些驱动程序时,您必须通过多个层(包括抽象层和COM互操作层)进行访问。抽象层负责资源管理,例如管理内存句柄以确保正确执行垃圾回收,将数据类型和参数更改为.NET类型,并将oledb缓冲区转换为行和列绑定。COM互操作层则负责处理从.NET到COM和反向传递消息的排队,包括锁定/解锁/转换指针。

不要相信任何没有了解他们如何测试以及使用什么环境(托管代码与托管代码)的人对OleDB性能做出虚假指控的言论。唯一会减慢OleDB速度的是需要进行大量管道工作以使本机代码与托管代码良好配合。也要记住,SqlClient .NET库具有自己的管道,而且并不像大多数人认为的那样是一个本地.NET库。.NET中的SqlClient库使用SNINativeMethodWrapper和SNIPacket类,这些类是在非托管代码(sqlncli.dll)和托管.NET代码之间传递数据的包装器。这是未经宣传的真相,也是为什么在使用本机非托管代码中使用OleDB时,.NET SqlClient永远无法超越OleDB的原因。

总之,如果您正在使用100%托管代码,则从System.data.SqlClient中获取更好的性能。如果您有混合环境,则直接与OleDB或sqlncli.dll(SQL2005)或sqlncli10.dll(SQL 2008)交互可以获得更好的性能。请记住,Microsoft正在更新OLEDB和ODBC,并且最新的OLEDB驱动程序确实与最新的非托管本地SQL客户端库进行交互。Microsoft建议在需要高性能的非托管应用程序中使用OleDB。

有关更多信息,请参见“SQL Server 2008 Books Online\Database Engine\Development\Developer's Guide\SQL Server 2008 Native Client Programming\SQL Server 2008 Native Client (OLE DB)”。


3

这里是一些用于直接比较的PowerShell代码:

Ole-DB:

$ConnectionString      = "server=localhost;database=MyDatabase;trusted_connection=yes;Provider=SQLNCLI10;"
$sql = "SELECT * FROM BigTable"

$conn = New-Object System.Data.OleDb.OleDbConnection($ConnectionString)
$conn.open()
$cmd = New-Object system.Data.OleDb.OleDbCommand($sql,$conn)
#$cmd.CommandTimeout = $timeout
$da = New-Object system.Data.OleDb.OleDbDataAdapter($cmd)
$dt = New-Object system.Data.datatable
[GC]::Collect()
$start = get-date
[void]$da.fill($dt)
$now = get-date
[int]($now - $start).Milliseconds
$conn.close()
#$dt

SQLClient:

$ConnectionString      = "Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True"
$sql = "SELECT  * FROM BigTable"


$conn=new-object System.Data.SQLClient.SQLConnection($ConnectionString) 
$conn.Open() 
$cmd=new-object System.Data.SQLClient.SQLCommand($sql,$conn)
#   $cmd.CommandTimeout=$timeout
$dt = New-Object system.Data.datatable
$da=New-Object System.Data.SQLClient.SQLDataAdapter($cmd)
[GC]::Collect()
$start = get-date
[void]$da.fill($dt)
$now = get-date
[int]($now - $start).Milliseconds
$conn.close()
#$dt

我得到了

Ole-DB : SQL-Client
538 - 839
767 - 456
592 - 678

因此,对于这种类型的即席查询,我更喜欢使用Ole-DB,因为我只需要调整连接字符串就可以从Oracle数据库中提取数据。


1
我只需要调整连接字符串就可以从Oracle数据库中提取数据。但是,不同的OleDB提供程序不支持的内容可能会令人惊讶。例如,使用Oracle的提供程序时命令不会超时 - Conrad Frix

3
我和 Joel 在这方面是一致的,如果你计划继续使用 SQL Server,则 SqlClient 是最好的选择。虽然有性能提升,但通常需要开始处理大型数据集和高数量的事务才能看到其优势。
总体而言,提供的错误和功能更加符合 SQL Server 的要求,因此可以说是一种“更好”的实现。它还支持 MARS,对于某些人来说这是必须使用的开关。

2
您可以编写一个使用SqlClient和OleDB执行一些典型操作的样本应用程序,并对它们进行基准测试以比较性能。我怀疑差异不会很大,但只有一种方法可以找出答案。
我认为,除非您使用像XML这样的奇特数据类型,否则您在使用OleDb时不会遇到任何问题,如果是这种情况,您可能需要花费更多的功夫。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接