2016-11-29 77 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。