在c#中,按id在数据库中查找记录的最快方法是什么

本文关键字:方法 是什么 数据库 id 查找记录 | 更新日期: 2023-09-27 18:26:24

我使用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();

而且速度更快。

有更好更快的方法吗?

在c#中,按id在数据库中查找记录的最快方法是什么

无论你(定期)搜索什么,都需要在数据库中定义一个索引,以获得最佳速度。请注意,某些列和某些类型的搜索不能很好地索引(例如,大文本字段或"包含"搜索),可能需要不同类型的索引(全文)。在您的情况下,您似乎正在使用主键,主键上应该有一个聚集索引

一旦定义了索引,就需要执行利用索引的查询。第一个查询执行完整的表扫描,将所有结果加载到内存中,然后在代码中迭代。您没有给数据库任何机会来帮助您加快查询速度,并且传输的数据比您需要的多得多。第二个查询允许数据库使用索引,通过添加指定索引列的where子句,只查找您感兴趣的行。如果是孤立地进行的(即,您只查找这一行,而不是按顺序查找每一行),那么它是最优的。它对该行执行索引查找,然后仅将该行传输到应用程序。

如果它实际上是主键,那么您可以通过使用SingleOrDefault来提高可读性,但不能提高性能,因为表中只能有一行具有该键。强制查询的单一性也将有助于检测潜在的错误,尽管不是在主键的上下文中,如果您有一个期望唯一但不是唯一的列。在这种情况下,如果找到多个结果,SingleOrDefault将抛出异常,而FirstOrDefault只会选择集合中的第一个结果,而不会向您提供任何关于不一致性的信息。

第二个更快,因为它在查询数据库时生成了一个where子句,类似于WHERE ID = <whatever>,它只向应用程序返回匹配的行。

第一个很慢,因为它从数据库中的Cities表中读取每一条记录,并将它们全部复制到应用程序中,而应用程序会丢弃除一条之外的所有记录。

如果您还没有,那么在Cities表的ID列上创建索引(或者更可能是主键)会使速度更快,尤其是在向表中添加更多数据时。

您的第二个代码示例应该是实现的最快方法

linq语句是最好的。在后台,它必须将linq语句和firstorddefault转换为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();
    }
}