3

好的。我正在使用 C# 编程语言访问一个简单的数据库(在 Microsoft SQL Server 上)

目前,我正在使用 DataReader 对象来访问数据库。所以这是我的问题:是否可以对特定的数据进行二进制搜索(在 C# 中),以便我可以加快搜索速度?

目前,我正在使用一个简单的 while 循环来搜索数据库的内容。我相信这是按顺序完成的。

while (pReader.Read())
{
   if ((String)pReader["theData"] == "The_thing_im_searching_for")
   break;
}

那么有没有办法进行二分查找呢?

4

6 回答 6

21

如果您仍然使用数据库,您应该编写一个 select 语句来搜索您要查找的内容,而不是手动遍历数据库。没有理由重新发明轮子。

于 2009-11-24T01:43:13.973 回答
6

As Donnie points out, if you express your predicate in SQL, the database will select the most efficient way of extracting your data automatically.

Try this:

string sql = "SELECT * FROM Foo WHERE theData = 'The_thing_im_searching_for'"
SqlDataAdapter adapter = new SqlDataAdapter(sql);
DataTable table = new DataTable();
adapter.Fill(table);

foreach(DataRow row in table.Rows) {
    // Do whatever you want here
}
于 2009-11-24T02:06:46.453 回答
3

本着 Donnies 回答的精神,我提供了一个简单的 SQL 示例,说明如何在使用比动态构造的 SQL 更安全的机制之后检索您的内容(正如其他人所建议的那样)

在简单的情况下,您应该为数据库中的每个实体为应用程序可用的每个 Create、Read、Update、Delete 操作创建一个存储过程。(这在大型生产系统中并不是 100% 正确,但它比在应用程序中构建的动态生成的 SQL 更好)

现在对于 READ,如果没有提供参数,这将列出所有内容。这是我工作中的数据库架构师讲授的一种方法的简化版本——这里我们没有将检索存储过程与列表过程分开,它们实际上是相同的操作。从长远来看,这将以更少的 SQL 代码来维护。

CREATE PROCEDURE usp_ReadName 
 @name_id bigint=NULL
AS
BEGIN
 SET NOCOUNT ON;
 if (@name_id IS NULL)
  SELECT name_id,name,description 
            from name with(nolock)
 else
  select name_id,name,description 
            from name with(nolock) 
            where name_id = @name_id  
END
GO

现在是 C# 方面。为了保存结果,我们定义了一个数据传输实体。一般来说,这些比数据表更轻,使用起来更快更有效。如果速度、大量数据或有限的内存不是问题,只需使用数据表即可。(平均而言,您将节省大约 40% 以上的内存和大约 10% 的速度 - 100K 以上结构的记录使用数据表的峰值内存使用量为 140MB,而 DTE 峰值为 78MB)

/// <summary>
/// A simple data transfer entity
/// </summary>
public struct name_data
{
    public long name_id;
    public string name;
    public string description;
    public name_data(long id, string n, string d)
    {
        name_id = id;
        name = n;
        description = d;
    }
}

现在我们使用可空参数语法在 C# 中捕获结果。此代码假定您已经打开了 sql 连接

conn.Open();
using (SqlCommand cmd = new SqlCommand("usp_ReadName",conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    if (id.HasValue)
        cmd.Parameters.Add("@name_id", SqlDbType.BigInt).Value = id.Value;
    using (SqlDataReader reader = cmd.ExecuteReader())
    {

        if (reader.HasRows)
        {
            while (reader.Read())
            {
                dte.name_data item = new dte.name_data(
                    (long)reader["name_id"],
                    reader["name"].ToString(),
                    reader["description"].ToString());
                items.Add(item);
            }
        }
    }
}
于 2009-11-24T04:43:41.457 回答
2

感谢您提供的所有信息(Jay Here 再次)。我相信我的问题已经得到解答。

问题是,我在数据库中有很多信息。搜索特定项目将花费大量时间。所以我对进行二进制搜索很感兴趣。

当我执行 SELECT 命令来查找某些内容时,我不知道 MSSQL(在后台)是否进行二进制搜索。但如果 R​​ickNZ(上图)所说的是真的

SQL Server 端直接 SELECT 的问题是数据库将在表中进行线性搜索,除非您正在使用的列上有索引;那么数据库可以更聪明。

如果我有“索引”信息,那么数据库将最有效地进行搜索(二进制搜索)。

于 2009-12-02T20:40:09.513 回答
0

那么有没有办法进行二分查找呢?

SQL Server 端直接 SELECT 的问题是数据库将在表中进行线性搜索,除非您正在使用的列上有索引;那么数据库可以更聪明。

如果您无论如何都需要阅读整个表格(例如,您可以稍后再搜索一次),那么您可以考虑使用ArrayList.BinarySearch(). 当然,要使其正常工作,数据需要在 ArrayList 中按排序顺序排列。

于 2009-11-24T09:28:27.497 回答
0

丹尼尔和唐尼在这里告诉你这是一个坏主意的回答是非常正确的。

但是,对您的问题更直接的回答是,是的,您可以搜索二进制数据,尽管我不确定这是否是您要查找的内容。

MSSQL 可以以 varbinary 格式存储数据,您可以在此 varbinary 数据上进行搜索。事实上,您可以在这篇文章中找到更多信息:Dealing with a varbinary field in VB.NET

这是执行此操作的查询示例。

byteArrayToken = StringToByteArray(stringToken)
scSelectThing.CommandText = "select thing from table where token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()
于 2009-11-24T02:21:37.703 回答