2009-11-22 21 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,該選項在運行時不需要解釋。

相關問題