3

名前ベースのルックアップは、整数インデックスの場合よりも複数の一致ルールを使用すると少し遅くなる可能性があることは理にかなっています。ただし、データ セット内の平均 10 ~ 15 [列] エントリ数について話しているときに、これが各行の 3% (または私のプロジェクトでは 5 ~ 7%) の相対コストを説明しているとは信じがたいです。 . データセット内のレコード数ではなく、この「逆参照」が発生する列の数を参照している前のステートメントで明確にする価値があります。上記のコストは、これらのルックアップが行ごとに 1 回発生するというコンテキストにあります。したがって、それらは頻繁に発生する可能性があります。

idr.GetOrdinal(name) // Name based lookup
idr[name]  // Name-based lookup
idr.GetValue(index) // Ordinal-based lookup

名前ベースのフィールド検索を行うために必要な、データベースとの追加の通信は実際にありますか? 何が彼らをそんなに遅くするのですか?

また、次のコードで列名を取得していることにも気付きました。

List<string> columnList = new List<string>();
for (int i = 0; i < idr.FieldCount; i++)
{
    columnList.Add(idr.GetName(i));
}

return columnList;

GetSchemaTable を使用した同等のバージョンよりもはるかに高速です。同じ理由によるものだと思います

この質問は、序数ベースのルックアップと名前ベースのルックアップの精神から生じます。

4

2 に答える 2

3

これは、ILSpy を使用してプルされた .NET 4.0のコードですGetOrdinalSqlDataReader

public override int GetOrdinal(string name)
{
    SqlStatistics statistics = null;
    int ordinal;
    try
    {
        statistics = SqlStatistics.StartTimer(this.Statistics);
        if (this._fieldNameLookup == null)
        {
            if (this.MetaData == null)
            {
                throw SQL.InvalidRead();
            }
            this._fieldNameLookup = new FieldNameLookup(this, this._defaultLCID);
        }
        ordinal = this._fieldNameLookup.GetOrdinal(name);
    }
    finally
    {
        SqlStatistics.StopTimer(statistics);
    }
    return ordinal;
}

ご覧のとおり、追加のデータベース アクセスはありません。FieldNameLookupを使用しHashtableてフィールド名を格納し、最初GetOrdinalに呼び出されたときにロードされた後にキャッシュされます。そのため、GetOrdinal呼び出しは を介し​​て行われるルックアップに非常に少量のオーバーヘッドを追加しますFieldNameLookup。また、SqlStatistics呼び出しによりオーバーヘッドが少し追加される場合もあります (おそらくそれほどではありません)。

良いテストは、 を使用しHashtableてインデックスを格納し、各行の各列のインデックスを検索することHashtableです。GetOrdinalパフォーマンスが各行の呼び出しと同じである場合、オーバーヘッドがFieldNameLookup呼び出しにあると安全に想定できます。

それが役立つことを願っています。

于 2013-04-29T19:59:42.780 に答える
1

.NET Framework オブジェクトのソースコードを検索して、内部で何が起こっているかを確認できます。この例から:

override public  Int32 GetOrdinal (string name) { 

            ValidateOpen("GetOrdinal");
            ValidateReader(); 
            DataColumn dc = currentDataTable.Columns[name];

            if (dc != null) {
                return dc.Ordinal;// WebData 113248 
            }
            else{ 
                throw ExceptionBuilder.ColumnNotInTheTable(name, currentDataTable.TableName); 
            }
        } 
于 2013-04-29T19:52:15.170 に答える