2013-04-29 18 views
3

有意義的是,基於名稱的查找可能會比使用多個匹配規則的整數索引慢一點。然而,當我們談論數據集中平均數量爲10-15 [列]條目時,我很難相信這解釋了每行的3%(或我的項目中的5-7%)相對成本。在之前的聲明中,我要指出的是,我指的是此「解除引用」所針對的列的數量,而不是數據集中記錄的數量。上述成本是在這些查詢每隔一行發生一次的情況下進行的。所以他們可能會出現很多。基於DataReader名稱的查找 - 底層實際發生了什麼,使得它們比循環中基於序數的查找慢得多?

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等效版本快,我猜這是出於同樣的原因。

這個問題出現在從精神: Ordinal-Based Lookups vs. Name Based Lookups

+0

如果* one *基於名稱的查找與100個基於名稱的查找之間存在差異,那麼我很好奇。換句話說,第一次查找是否將各種模式數據加載到內存中。 – 2013-04-29 19:39:52

回答

3

下面是GetOrdinalSqlDataReader代碼,.NET 4.0,使用ILSpy拉。

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調用中。

希望有所幫助。