如何比较通过LINQ到SQL和普通SQL Server的查询性能
本文关键字:SQL Server 性能 查询 LINQ 何比较 比较 | 更新日期: 2023-09-27 18:19:40
我想比较三种方法的查询执行性能:
- 对类型化数据集的查询
- 使用LINQ to SQL进行查询
- 直接在SQL Server 2008 R2上执行SQL查询
因此,我想运行一些测试szenarios,如下所示:
查询类型化数据集
在这里,我使用数据集设计器创建了数据集。然后我查询相应的TableAdapter,如
var minDat = new DateTime(2014, 5, 1);
var maxDat = new DateTime(2014, 5, 2);
var ta = new MyTableAdapter();
vat res = (from row in ta.GetData()
where row.Date >= minDat && row.Date <= maxDat
select row).ToArray();
这会导致超时,因为它首先从数据库中的表中获取所有数据,并对接收到的对象执行查询。这是意料之中的事。
查询类型化数据集
我在Visual Studio 中使用O/R-Designer创建了一个LINQ到SQL类
var minDat = new DateTime(2014, 5, 1);
var maxDat = new DateTime(2014, 5, 2);
var context = new LtSqlDataContext();
var query = (from row in context.MyTable
where row.Date >= startTime && row.Date <= endTime
select row).ToArray; // I do the .ToArray() to actually receive the whole set of results, i guess here i am doing sth. wrong
这总共需要2294毫秒。到目前为止,这似乎是合理的。
SQL查询
当将LINQ到SQL查询的执行时间与在SQL Server Management Studio中执行的实际SQL查询进行比较时,情况变得越来越奇怪。
declare @min datetime2 = '20140501';
declare @max datetime2 = '20140502';
select *
from MyTable
where Date >= @min
and Date <= @max
这需要6秒多一点的时间,确切地说是6211毫秒(取自SQL Server Profiler-Batch Completed)。
这怎么可能
我想也许我没有正确理解LINQ to SQL的概念。我认为对查询调用ToArray()
会导致实际将查询元组转移到数组中。但是,当直接在服务器上执行时,这怎么会比查询快(大约3倍)呢?
有没有更好的方法来比较这两个概念的查询性能?
PS:LINQ to SQL生成的查询与SQL Server Mgmt Studio 中执行的查询相同
编辑:LINQ to SQL生成的查询看起来像下面的
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language Deutsch
set dateformat dmy
set datefirst 1
set transaction isolation level read committed
exec sp_executesql N'SELECT [t0].[Column1], [t0].[Column2], [t0].[Column3], [t0].[Column4], [t0].[Column5], [t0].[Date], [t0].[Column7]
FROM [Alle].[MyTable] AS [t0]
WHERE ([t0].[Date] >= @p0) AND ([t0].[Date] <= @p1)',N'@p0 datetime2(7),@p1 datetime2(7)',@p0='2014-05-01 00:00:00',@p1='2014-05-02 00:00:00'
我试过在SSMS中执行它,但它仍然需要6秒左右。。。。
这可能是由于非常不同的查询构造,特别是参数化和使用的日期时间类型。你可以在SSMS中比较:
或者你可以在SSMS中做同样的事情,只需:
declare @min datetime = '20140501', @max datetime = '20140502';
exec sp_executesql N'select *
from MyTable
where Date >= @min
and Date <= @max', N'@min datetime, @max datetime', @min, @max;
要在ADO.NET中执行与原始查询相同的测试,您需要一个参数化查询,并将值作为常规DateTime
传递,因为这将与其他查询进行很好的比较:
var minDat = new DateTime(2014, 5, 1);
var maxDat = new DateTime(2014, 5, 2);
using(var cmd = conn.CreateCommand()) {
cmd.CommandText = @"select *
from MyTable
where Date >= @min
and Date <= @max";
cmd.Parameters.AddWithValue("min", minDat);
cmd.Parameters.AddWithValue("max", maxDat);
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()) {...}
}
}
或者更简单地说,使用类似dapper的东西:
var minDat = new DateTime(2014, 5, 1);
var maxDat = new DateTime(2014, 5, 2);
var rows = conn.Query<SomeType>(@"select *
from MyTable
where Date >= @min
and Date <= @max", new { minDat, maxDat }).ToList();
其中CCD_ 3具有类似于表中的列的属性。
返回了多少行?
565173行返回
给你。SSMS处理许多行的速度较慢。您的基准测试无效。从应用程序中使用ADO.NET执行LINQ查询和SQL查询。遍历所有行。在ADO.NET版本中,检索所有列值以强制反序列化。
也许,随着ADO.NET速度的加快,持续时间现在将非常接近。
如果LINQ到SQL的速度仍然更快,则会出现其他问题,例如缓存计划或SET选项不正确。对于这样一个简单的问题,我会感到惊讶。