C# Linq Where比SQL Where快得多
我是SQL新手,我很难理解为什么Where语句如此低效 关于数据库的一点背景知识。这是一个用于存储图标的SQL Compact Edition数据库。一个项目可以有多个图标,每个图标可以有多个路径,每个路径由几何体、颜色和不透明度组成。大约有2000个图标,大约有12000条路径 我试图创建一个只返回属于给定项目的图标的查询C# Linq Where比SQL Where快得多,c#,sql-server,linq,C#,Sql Server,Linq,我是SQL新手,我很难理解为什么Where语句如此低效 关于数据库的一点背景知识。这是一个用于存储图标的SQL Compact Edition数据库。一个项目可以有多个图标,每个图标可以有多个路径,每个路径由几何体、颜色和不透明度组成。大约有2000个图标,大约有12000条路径 我试图创建一个只返回属于给定项目的图标的查询 SELECT Icons.Id, Icons.Name... etc FROM Icons INNER JOIN Projects ON Icons.FK_Project
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;
}
var iconTable=geticondafromdatabase()。其中(e=>e.Project==projectName);
私有列表geticondafromdatabase()
{
var getAlliconCommand=newsqlcecommand(//SQL以上);
返回returniconda(本地连接字符串,getAlliconCommand);
}
私有列表returniconda(字符串连接字符串,SqlCeCommand命令)
{
var icondatareturn=新列表();
使用(var连接=新SqlCeConnection(connectionString))
{
command.Connection=连接;
使用(命令)
{
尝试
{
connection.Open();
使用(SqlCeDataReader dataReader=command.ExecuteReader())
{
while(dataReader.Read())
{
icondatareturn.Add(新的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()),
颜色=数据读取器[“颜色”].ToString().Trim(),
Opacity=double.Parse(dataReader[“Opacity”].ToString().Trim()),
ispathcomact=bool.Parse(dataReader[“Compact”].ToString().Trim()),
ZOrder=int.Parse(dataReader[“ZOrder”].ToString().Trim())
});
}
}
}
}
返回icondatareturn;
}
我不明白为什么返回每个图标,然后自己过滤掉结果会快得多。对此没有一般性的答案。您的性能值将在很大程度上取决于数据库大小和使用的索引等因素。如果表中有很多行,并且在
Icons.FK\d上有索引
非常有选择性(例如,您只选择了100万行中的10行),我怀疑加载所有行并使用LINQ进行选择会更快,因为DB可以使用索引进行搜索操作(fast),并且只返回行的一小部分(也很快)
另一方面,如果您没有索引,并且选择了行的一大个子集(例如2500行中的2000行),SQL Server将首先执行聚集索引扫描,然后再返回数据集的几乎所有行。此附加操作将占用大部分执行时间,并且不会显著减少结果集的大小
您应该做的是比较有无执行计划,看看是否可以优化查询。在数据库级别上进行调优通常比在客户端进行调优更可取。这本身不是一个答案,但可能对将来的任何人都是一个有用的解决方案。我在SQLite中实现了完全相同的功能,并且能够数据将在0.03秒内返回,而无需自己执行任何linq。您显示的是sql,但您谈论的是linq。您可以显示真正的C代码吗?sql查询是实际执行的还是您认为它是什么?您在显示的代码中根本没有使用
iconTable
,但您使用的是dataReader
,您没有反编译clared…很难理解你在做什么。你在下一次执行时清除了sql缓存吗?旁注:不要将所有内容都转换为字符串,然后返回到正确的类型,例如使用double.Parse(dataReader[“Opacity”].ToString().Trim())
。而是将其存储为正确的类型,然后使用dataReader.GetDouble(opacityIndex)
Icons.FK_projectd是否已编制索引?我刚刚运行了在Icons上创建索引IconIdIndex(FK_projectd)
。它说它成功了,但对性能没有影响。如果SQL Server选择使用索引,索引可能会产生影响。如果它估计不会产生很大影响(例如,不太有选择性——例如第二段中的示例),它可能仍然会忽略它。这就是为什么根据执行计划进行DB性能调整很重要的原因。此外,您的查询中有多个JOIN
s,因此您可能还需要一些其他索引。我将看看是否可以找到有关如何评估执行计划的教程。谢谢。