SqlDataReader - это одно и то же. Какой из них быстрее

Я работаю с SqlXml и хранимой процедурой, которая возвращает xml, а не необработанные данные. Как на самом деле читать данные, когда они возвращаются в виде xml и не знают об именах столбцов. Я использовал приведенные ниже версии и слышал, что получение данных из SqlDataReader через порядковый номер выполняется быстрее, чем через имя столбца. Пожалуйста, посоветуйте, что лучше и с уважительной причиной или доказательством

  1. sqlDataReaderInstance.GetString(0);

  2. sqlDataReaderInstance[0];


person Deeptechtons    schedule 20.10.2011    source источник
comment
@Kangkan, я считаю, что метод тоже зависит от индексатора, поправьте меня, если я ошибаюсь!   -  person Deeptechtons    schedule 20.10.2011
comment
Связано: datareader-hardcode-ordinals   -  person nawfal    schedule 28.11.2013
comment
Эта ссылка: blog.maskalik.com/ado-net/data- Оптимизация производительности чтения говорит, что reader.GetString(0) будет работать быстрее. Хотя я скептически отношусь к его таймингам, я думаю, что в целом он прав.   -  person nawfal    schedule 31.07.2015


Ответы (3)


и слышал, что получение данных из SqlDataReader через порядковый номер быстрее, чем через имя столбца

Оба ваших примера получают данные через индекс (порядковый номер), а не имя столбца:

Получение данных через имя столбца:

while(reader.Read())
{
    ...
    var value = reader["MyColumnName"];
    ...
}

потенциально медленнее, чем получение данных через индекс:

int myColumnIndex = reader.GetOrdinal("MyColumnName");
while(reader.Read())
{
    ...
    var value = reader[myColumnIndex];
    ...
}

потому что первый пример должен неоднократно находить индекс, соответствующий "MyColumnName". Если у вас очень большое количество строк, разница может быть даже заметной.

В большинстве ситуаций разница не будет заметна, поэтому отдавайте предпочтение удобочитаемости.

ОБНОВЛЕНИЕ

Если вас действительно беспокоит производительность, альтернативой использованию порядковых номеров является использование DbEnumerator следующим образом:

foreach(IDataRecord record in new DbEnumerator(reader))
{
    ...
    var value = record["MyColumnName"];
    ...
}

Класс DbEnumerator считывает схему один раз и поддерживает внутреннюю хеш-таблицу, которая сопоставляет имена столбцов с порядковыми номерами, что может повысить производительность.

person Joe    schedule 20.10.2011
comment
Джо, я считаю, что все основные коннекторы ADO.NET поддерживают внутреннюю хеш-таблицу для сопоставления имени столбца с порядковым номером. Я подтвердил для SQLite и MySQL. Таким образом, запись [строка] в любом случае довольно эффективна (я имею в виду даже без класса DbEnumerator). Но я думаю, что такое обучение читателя, как вы, имеет свои преимущества. - person nawfal; 31.07.2015
comment
используя обновленное решение, я получаю следующую ошибку: оператор foreach не может работать с переменными типа System.Data.Common.DbEnumerator' because it does not contain a definition for GetEnumerator' или недоступен - person Federico Caccia; 01.05.2019

По сравнению со скоростью получения данных с диска оба будут одинаково быстрыми.

Эти два вызова не эквивалентны: версия с индексатором возвращает объект, тогда как GetString() преобразует объект в строку, вызывая исключение, если это невозможно (т. е. столбец DBNull).

Таким образом, хотя GetString() может быть немного медленнее, при его использовании вы все равно будете приводить к строке.

Учитывая все вышесказанное, я бы использовал GetString().

person Jeremy McGee    schedule 20.10.2011
comment
+1 @Jeremy, я бы отметил этот ответ, если бы вы предоставили какой-то профиль, доказательство - person Deeptechtons; 20.10.2011

Indexer работает быстрее, поскольку возвращает данные в собственном формате и использует порядковый номер.

Взгляните на эти темы:

  1. Максимальная производительность с помощью SqlDataReader
  2. .NET SqlDataReader Item[] vs. GetString(GetOrdinal())?
person kv-prajapati    schedule 20.10.2011
comment
значит ли это, что я также могу сделать instance.Item[0] ? - person Deeptechtons; 20.10.2011