我使用DataContext.CreateDatabase创建了一个数据库,并在其中插入了记录。
里面有很多记录,所以我希望以最快的方式找到它的id。
首先我尝试了:
foreach (var currentRecord in _context.Cities)
{
if (currentRecord.ID == recordIdToFind)
return currentRecord;
}
但它很慢,所以我把它改成了:
var recordToReturn = from r in _context.Cities
where r.ID == recordIdToFind
select r;
return recordToReturn.FirstOrDefault();
并且加快了速度。
有更好的方法吗?
答案 0 :(得分:2)
无论您正在搜索(定期),都需要在数据库中定义索引以获得最佳速度。请注意,某些列和某些类型的搜索不能很好地索引(例如,大文本字段或“包含”搜索),并且可能需要不同类型的索引(全文)。在您的情况下,您似乎正在使用主键,主键上应该有聚簇索引。
一旦定义了索引,就需要执行利用索引的查询。第一个查询执行全表扫描,将所有结果加载到内存中,然后在代码中迭代它们。您没有给数据库任何机会来帮助您加快查询速度并传输比您需要的更多数据。第二个查询允许数据库使用索引通过添加指定索引列的where子句来查找您感兴趣的行。如果孤立地完成(即,你只是查找这一行,而不是按顺序查找每一行),那么它是最佳的。它对该行执行索引查找,然后将该行仅传输到您的应用程序。
如果它实际上是主键,那么您可以通过使用SingleOrDefault
来提高可读性,尽管不是性能,因为表中只能有一行包含该键。强制查询的单一性也有助于检测潜在的错误,但不是在主键的上下文中,如果您有一个您希望是唯一但不是唯一的列。在这种情况下,如果找到多个结果,SingleOrDefault
将抛出异常,而FirstOrDefault
将只选择集合中的第一个,而不会向您提供有关不一致的任何信息。
答案 1 :(得分:2)
第二个变得更快,因为它在查询数据库时生成了一个where子句,类似于WHERE ID = <whatever>
,它只返回匹配的行到你的应用程序。
第一个是缓慢的,因为它从数据库中的Cities表中读取每个记录,并将它们全部复制到您的应用程序中,从而丢弃除了其中一个之外的所有记录。
如果您还没有,则Cities表的ID列上的索引(或更可能是主键)将使这一点更快,尤其是当您向表中添加更多数据时。
答案 2 :(得分:1)
你的第二个代码示例应该是最快的方法
答案 3 :(得分:0)
linq声明和它一样好。它必须将linq语句和firstordefault转换为SQL服务器的语句。在检索结果时,它会将其映射到城市对象中。
所以它实际上是以类似于这个准备好的声明的方式发送的:
SELECT TOP 1 * FROM Cities where ID=@ID
理论上你可以通过如下自己发送准备好的声明来加速它,但它不会给你城市对象,并且在大多数情况下不会明显更快:(让我重复,这不太可能你想做什么,但这是获取数据的更快方式)
string commandText = "SELECT TOP 1 * FROM Cities where ID=@ID;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("@ID", SqlDbType.Int);
command.Parameters["@ID"].Value = recordIdToFind;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}