2009-11-22 66 views
7

我已经比较了两个从数据库表中获取相当大数据的查询。对于查询一,我使用Linq To Sql,另一个我通过ADO.NET使用passthrough SQL。为什么Linq将Sql数据绑定到gridview比传递SQL慢得多?

我知道Linq To Sql必须在幕后做很多工作,但它究竟在做什么?这两个查询获取的数据量相同,但Linq To Sql查询速度慢了5秒,并且使用了150MB的RAM!

这里是我的测试代码:

使用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(); 
    } 

直通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(); 
    } 
+2

当进程没有连接到调试器时,你测试过了吗? – 2009-11-22 17:08:56

+0

我发现与NHibernate类似的问题。 我不确定在屏幕后面有什么大的seceret,但我猜测ORM工具很慢...... – Dani 2009-11-22 17:13:39

+1

@Dani - “数据绑定性能试验并不遵循”ORM工具很慢“。这是一个非常**一般(和恕我直言,误导)声明。 – TrueWill 2009-11-22 17:44:57

回答

8

LINQ2SQL正在恢复其中的数据集得到填充有什么本质上相当于一个强类型对象哈希表。

在Linq中,数据的种群以及数据绑定到GridView会使用大量的反射来生成所需的结果。

在第二段代码中,数据正在加载到数据集中并绑定到GridView。这本质上是加载一个包含数据和查找的散列表来绑定。

散列表操作总是比反射速度快。有了少量的数据,就不会有明显的差异,但对于大量的数据,您将会看到Linq中反射的影响。

+0

谢谢你的回答。我需要一个答案。什么是反思? – Poku 2009-11-22 17:40:51

+1

反射是以编程方式发现对象或类型的属性,方法,事件的过程。查看MSDN上的System.Reflection名称空间。这是Linq必须做的,以便将查询返回的值分配给tDokument对象的属性。 它比直接属性分配慢得多。 – Jason 2009-11-22 17:52:23

4

你看实际的SQL发送到带有Profiler的SQL Server?

在这种情况下,我怀疑这是客户端如何处理它(数据集vs列表),这是造成差异,但我远不及c#专家附近。

+0

数据集将比通用列表拥有更多的开销,所以这真的不应该成为问题。 – Jason 2009-11-22 16:59:46

+0

@Jason:谢谢。我认为列表会。 – gbn 2009-11-22 17:01:28

1

您的措施可能是不准确的,请使用System.Diagnostics.StopWatch类时间测量:

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

合理的建议(尽管可能应该是一个评论)。显然Thread.Sleep可能会导致线程睡眠超过100毫秒。 – RichardOD 2009-11-22 17:04:37

+0

是的,但是当我运行上面的程序时,打印结果略小于100ms – 2009-11-22 17:06:02

+0

注释不会启用代码格式 – 2009-11-22 17:06:57

3

捕获并分析通过Linq To Sql示例中的线路发送的SQL语句。 SQL事件探查器将做的伎俩。

使用Management Studio直接针对您的SQL Server运行示例1和2中的那些语句。可能你在查询计划中看不到任何实质性差异。我认为大部分时间都花在构建C#对象上(我认为是Jason's answer nails it)。

2

Linq to Sql必须从您的代码中找出针对数据库运行的查询类型,然后必须将查询结果转换为强类型对象,这意味着将进行强制类型转换。这是你的DataSet版本不能做的两件事。

如果您对Linq to Sql性能感兴趣,可以选择使用compiled queries,该选项在运行时不需要解释。

相关问题