简体   繁体   English

为什么Linq To Sql数据绑定到gridview比传递SQL慢得多?

[英]Why is Linq To Sql databinding to gridview much slower than pass-through SQL?

I have compared two queries which fetch some fairly large data from a database table. 我比较了从数据库表中获取一些相当大的数据的两个查询。 For query one I used Linq To Sql and for the other I use passthrough SQL via ADO.NET. 对于查询一个我使用Linq To Sql而另一个我通过ADO.NET使用passthrough SQL。

I know that Linq To Sql has to do a lot of work behind the scenes, but what is it actually doing? 我知道Linq To Sql必须在幕后做很多工作,但实际上它在做什么? The two queries fetches the same amount of data but the Linq To Sql query is more than 5 seconds slower and uses 150mb more RAM! 这两个查询获取相同数量的数据,但Linq To Sql查询速度慢了5秒以上,并且使用了150多个RAM!

Here is my test code: 这是我的测试代码:

Using Linq To Sql : 使用Linq To Sql:

public void MakeList()
    {
        int start = Environment.TickCount;
        var document = from d in _dm.tDokuments select d;

        List<tDokument> documentList = document.ToList();
        int end = Environment.TickCount;

        GridView1.DataSource = documentList;
        GridView1.DataBind();

        Label1.Text = (end - start).ToString();
    }

Passthrough SQL + ADO.NET: 直通SQL + ADO.NET:

public void MakeList()
    {

        int start = Environment.TickCount;
        SqlCommand sqlCommand = new SqlCommand("SELECT * FROM tDokument", _connection);
        SqlDataAdapter da = new SqlDataAdapter(sqlCommand);

        DataSet ds = new DataSet();
        da.Fill(ds);
        int end = Environment.TickCount;

        GridView1.DataSource = ds;
        GridView1.DataBind();

        Label1.Text = (end - start).ToString();
    }

Linq2Sql is returning strongly typed objects where as the dataset is getting populated with what essentially amounts to a hash table. Linq2Sql返回强类型对象,其中数据集的填充基本上等于哈希表。

In Linq, the population of the data and the binding of that data to a GridView uses a lot of reflection to generate the desired results. 在Linq中,数据的填充以及该数据与GridView的绑定使用大量反射来生成所需的结果。

In the second piece of code, the data is being loaded into a dataset and binded to a GridView. 在第二段代码中,数据被加载到数据集中并绑定到GridView。 This is essentially loading a hashtable with data and lookups to bind. 这实际上是加载一个哈希表,其中数据和查找要绑定。

Hashtable operations are always going to be faster than reflection. Hashtable操作总是比反射更快。 With a small amount of data, there is not going to be a noticeable difference but for lots of data, you will see the impact of reflection in Linq. 对于少量数据,不会有明显的差异,但对于大量数据,您将看到Linq中反射的影响。

Have you looked at the actual SQL being sent to SQL Server with Profiler? 您是否查看过使用Profiler发送到SQL Server的实际SQL?

In this case I suspect it's how the client is handling it (DataSet vs List) that is causing the difference, but I'm nowhere near ac# expert. 在这种情况下,我怀疑它是客户端如何处理它(DataSet vs List)导致差异,但我远不及ac#expert。

Capture and analyze the SQL statement(s) that are being sent over the wire in your Linq To Sql example. 捕获并分析Linq To Sql示例中通过线路发送的SQL语句。 SQL Profiler will do the trick. SQL Profiler可以解决这个问题。

Run both those statements from Example 1 and 2 directly against your SQL Server using Management Studio. 使用Management Studio直接针对SQL Server运行示例1和2中的那些语句。 Likely you won't see ANY substantial difference in the query plan. 可能你不会在查询计划中看到任何实质性的差异。

I think the majority of time is spent in constructing the C# objects ( Jason's answer nails it , I think). 我认为大部分时间花在构建C#对象上(我认为Jason的回答是指甲 )。

Linq to Sql has to figure out from your code what kind of query to run against the database then it has to translate the results of the query into strongly typed objects, which means casting will occur. Linq to Sql必须从你的代码中弄清楚对数据库运行什么样的查询然后它必须将查询的结果转换为强类型对象,这意味着将进行转换。 That's two things your DataSet version doesn't do. 这是DataSet版本没有做的两件事。

If you're interested in Linq to Sql performance, there is the option of using compiled queries which removes the need for interpretation at runtime. 如果您对Linq to Sql性能感兴趣,可以选择使用编译查询 ,这样就无需在运行时进行解释。

Your measure may not be accurate, please use the System.Diagnostics.StopWatch class for time measurement: 您的度量可能不准确,请使用System.Diagnostics.StopWatch类进行时间测量:

static void Main(string[] args)
{
    var sw = Stopwatch.StartNew();
    Thread.Sleep(100);
    Console.WriteLine(sw.Elapsed.ToString());
    Console.Read();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM