2016-11-29 72 views
4

我是SQL的新手,並且在理解Where Where語句效率如此低下時遇到了一些麻煩。Linq比SQL更快的地方Where Where

數據庫的一點背景。這是一個用於存儲圖標的SQL Compact Edition數據庫。一個項目可以有多個圖標,每個圖標可以有多個路徑,每個路徑由幾何,顏色和不透明度組成。大約有2000個圖標,這導致大約12000個路徑。

enter image description here

我試圖創建一個查詢僅返回屬於特定項目

SELECT Icons.Id, Icons.Name... etc FROM Icons 
INNER JOIN Projects ON Icons.FK_ProjectId = Projects.Id 
INNER JOIN IconDetails ON Icons.Id = IconDetails.FK_IconId 
INNER JOIN Paths ON IconDetails.FK_PathId = Paths.Id 
INNER JOIN Colours ON IconDetails.FK_ColourId = Colours.Id 
WHERE (Icons.FK_ProjectId = 5) 

這需要〜2.8秒就可以完成的圖標。但是,如果我刪除底部的Where聲明,它只需要約0.3秒。然後我可以使用C#Linq來選擇它們屬於我想要的項目的所有圖標。

var iconTable = GetIconDataFromDatabase().Where(e => e.Project == projectName); 


private List<IconData> GetIconDataFromDatabase() 
{ 
    var getAllIconsCommand = new SqlCeCommand(// SQL Above); 

    return ReturnIconData(LOCAL_CONNECTION_STRING, getAllIconsCommand); 
} 

private List<IconData> ReturnIconData(string connectionString, SqlCeCommand command) 
{ 
    var IconDataToReturn = new List<IconData>(); 

    using (var connection = new SqlCeConnection(connectionString)) 
    { 
     command.Connection = connection; 

     using (command) 
     { 
      try 
      { 
       connection.Open(); 

       using (SqlCeDataReader dataReader = command.ExecuteReader()) 
       { 
        while (dataReader.Read()) 
        { 
         IconDataToReturn.Add(new IconData 
         { 
          Id = int.Parse(dataReader["Id"].ToString().Trim()), 
          Project = dataReader["ProjectName"].ToString().Trim(), 
          Name = dataReader["Name"].ToString().Trim(), 
          Geometry = Geometry.Parse(dataReader["Geometry"].ToString().Trim()), 
          Colour = dataReader["Colour"].ToString().Trim(), 
          Opacity = double.Parse(dataReader["Opacity"].ToString().Trim()), 
          IsPathCompact = bool.Parse(dataReader["Compact"].ToString().Trim()), 
          ZOrder = int.Parse(dataReader["ZOrder"].ToString().Trim()) 
         }); 

        } 
       } 
      } 
     } 
    return IconDataToReturn; 
} 

我不明白如何能夠更快地返回每一個圖標,然後自己過濾掉結果。

+3

你顯示的是sql,但你正在談論LINQ。你能展示真正的C#代碼嗎? sql查詢是什麼實際執行或者你認爲它是什麼? –

+2

您在所顯示的代碼中完全沒有使用'iconTable',但是您使用的是未聲明的'dataReader' ...這很難遵循您正在做的事情。 –

+1

您是否清除下一次執行的sql緩存? – mybirthname

回答

3

對此沒有一般的答案。您的性能值將取決於數據庫大小和使用的索引等因素。如果你的表中有很多行,並且你有一個非常有選擇性的Icons.FK_ProjectId索引(例如,你只選擇了10百萬行),但我懷疑加載所有行並選擇LINQ會更快,因爲數據庫可以使用索引進行查找操作(快速),並只返回一小部分行(也是快速)。

另一方面,如果你沒有索引,並且你選擇了很大一部分行(例如2500行中有2000行),SQL Server首先必須執行聚簇索引掃描,然後才能發現幾乎所有的行的數據集。這個額外的操作將佔用執行時間的最大部分,並且不會顯着減小結果集的大小。

你應該做的是比較你的執行計劃與不在哪裏,看看你是否可以優化你的查詢。在數據庫級調整通常更適合在客戶端調整。

+0

我剛剛運行了'CREATE INDEX IconIdIndex ON圖標(FK_ProjectId)'。它說它是成功的,但它對性能沒有影響。 – Ralt

+0

索引_can_有效,_if_ SQL Server選擇使用它。如果它估計它不會有很大的不同(例如,不是很有選擇性 - 例如第二段中的例子),它可能仍然會忽略它。這就是爲什麼根據執行計劃進行數據庫性能調整非常重要的原因。 – Sefe

+0

此外,您的查詢中有多個「JOIN」,因此您可能還需要其他一些索引。 – Sefe

0

本身並不是一個答案,但可能是一個有用的解決方案,任何人看未來。我在SQLite中實現了完全相同的功能,並且能夠在0.03秒內恢復數據,並且無需親自執行任何LINQ。