我是SQL的新手,我很难理解为什么这个Where语句效率低下。
数据库的一些背景知识。它是一个SQL Compact Edition数据库,用于存储图标。项目可以有多个图标,每个图标可以有多个路径,每个路径都由几何图形,颜色和不透明度构成。大约有2000个图标,大约有12000个路径。
我试图创建一个只返回属于给定项目的图标的查询
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;
}
我不明白如何更快地返回每个图标,然后自己过滤掉结果。
答案 0 :(得分:3)
对此没有一般性的答案。您的性能值将在很大程度上取决于数据库大小和使用的索引等因素。如果你的表中有很多行,并且Icons.FK_ProjectId
上有一个非常有选择性的索引(例如你只选择了10万行),我怀疑加载所有行并选择更快使用LINQ,因为DB可以使用索引进行搜索操作(快速)并且只返回一小部分行(也很快)。
另一方面,如果你没有索引并且你选择了一大部分行(例如2500行中的2000个),那么SQL Server首先必须执行聚簇索引扫描,然后才会回显几乎所有的行。数据集。此附加操作将占用执行时间的最佳部分,并且不会显着减小结果集的大小。
您应该做的是比较执行计划与否在哪里,看看您是否可以优化查询。在数据库级别进行调优通常更适合在客户端进行调优。
答案 1 :(得分:0)
本身不是答案,但可能是对未来任何人都有用的解决方案。我在SQLite中实现了完全相同的功能,并且能够在0.03秒内恢复数据,而无需自己执行任何linq。