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

Donnie が指摘するように、述語を SQL で表現すると、データベースはデータを抽出する最も効率的な方法を自動的に選択します。

これを試して:

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 answer の精神で、動的に構築された SQL よりも安全なメカニズムを使用した後に、現在のものを取得する方法の簡単な SQL の例を提供しました (他の人がアドバイスしたように)。

単純なケースでは、データベース内のエンティティごとに、アプリケーションで使用可能な作成、読み取り、更新、削除操作ごとにストアド プロシージャを作成する必要があります。(これは大規模な実稼働システムでは 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% の速度を節約できます。DTE は 78MB でピークに達しますが、データテーブルでは 140MB でピークメモリ使用量を超える構造の 100K レコード)

/// <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;
    }
}

ここで、null 許容パラメーター構文を使用して 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

すべての情報をありがとう(再びここにジェイ)。私は私の質問に答えてもらうと信じています。

問題は、データベースにたくさんの情報があるということです。特定のアイテムの検索には多くの時間がかかります。だから私は二分探索をすることに興味がありました。

SELECTコマンドを実行して何かを検索すると、MSSQL(バックグラウンド)がバイナリ検索を実行するかどうかがわかりません。しかし、RickNZ(上記)の言うことが本当なら

SQL Server側のストレートSELECTの問題は、作業している列にインデックスがない限り、DBがテーブルを線形検索することです。そうすれば、DBをよりスマートにすることができます。

次に、情報が「インデックス化」されている場合、データベースは最も効率的に検索(バイナリ検索)を実行します。

于 2009-12-02T20:40:09.513 に答える
0

ここでのダニエルとドニーの回答は、これは悪い考えだと言っていますが、これは非常に正しいです。

ただし、あなたの質問に対するより直接的な答えは、はい、バイナリデータを検索できるということですが、これがあなたが探しているものかどうかはわかりません。

MSSQL はデータを varbinary 形式で保存でき、この varbinary データを検索できます。実際、この投稿で詳細情報を見つけることができます: VB.NET での varbinary フィールドの処理

これを行うクエリの例を次に示します。

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 に答える
0

二分探索を行う方法はありますか?

SQL Server 側での単純な SELECT の問題は、使用している列にインデックスがない限り、DB がテーブルを介して線形検索を実行することです。その場合、DB はよりスマートになります。

とにかくテーブル全体を読み取る必要がある場合 (たとえば、短時間で再度検索できるようにするため) は、ArrayList.BinarySearch(). もちろん、それが機能するには、データが ArrayList 内でソートされている必要があります。

于 2009-11-24T09:28:27.497 に答える