Есть ли дополнительные затраты при поиске столбца в DataTable по имени, а не по индексу? - PullRequest
3 голосов
/ 13 апреля 2010

В объекте DataTable добавлены ли издержки при поиске значения столбца по имени thisRow("ColumnA"), а не по индексу столбца thisRow(0)? В каких случаях это может быть проблемой.

Я работаю в команде, у которой есть большой опыт написания кода VB6, и я заметил, что не выполнял поиск столбцов по имени для DataTable объектов или сеток данных. Даже в коде .NET мы используем набор целочисленных констант для ссылки на имена столбцов в этих типах объектов. Я спросил руководителя нашей команды, почему это так, и он упомянул, что в VB6 было много накладных расходов при поиске данных по имени столбца, а не по индексу. Это все еще верно для .NET?


Пример кода (в VB.NET, но то же самое относится и к C #):

Public Sub TestADOData()
Dim dt As New DataTable

'Set up the columns in the DataTable    '
dt.Columns.Add(New DataColumn("ID", GetType(Integer)))
dt.Columns.Add(New DataColumn("Name", GetType(String)))
dt.Columns.Add(New DataColumn("Description", GetType(String)))

'Add some data to the data table    '
dt.Rows.Add(1, "Fred", "Pitcher")
dt.Rows.Add(3, "Hank", "Center Field")

'Method 1: By Column Name   '
For Each r As DataRow In dt.Rows
  Console.WriteLine( _
   "{0,-2} {1,-10} {2,-30}", r("ID"), r("Name"), r("Description"))
Next

Console.WriteLine()

'Method 2: By Column Name   '
For Each r As DataRow In dt.Rows
  Console.WriteLine("{0,-2} {1,-10} {2,-30}", r(0), r(1), r(2))
Next

End Sub

Есть ли случай, когда метод 2 обеспечивает преимущество в производительности по сравнению с методом 1?

Ответы [ 5 ]

7 голосов
/ 13 апреля 2010

Да , должны быть небольшие накладные расходы, связанные с поиском столбцов по имени, а не по индексу. Я не стал бы беспокоиться об этом, , если только вы не продолжите искать тот же столбец в цикле, как в вашем примере кода. Потому что тогда небольшие издержки могут накапливаться до измеримых накладных расходов, в зависимости от количества строк в таблице.

Самый быстрый способ для доступа к значению определенного столбца некоторой строки - это поиск с использованием самого объекта DataColumn . Например:

Dim dt As DataTable = ...

Dim idColumn As DataColumn = dt.Columns("ID")
Dim nameColumn As DataColumn = dt.Columns("Name")
Dim descriptionColumn As DataColumn = dt.Columns("Description")

For Each r As DataRow In dt.Rows

    ' NB: lookup through a DataColumn object, not through a name, nor an index: '
    Dim id = r(idColumn)
    Dim name = r(nameColumn)
    Dim description = r(descriptionColumn)

    ...
Next

Последний совет: Я бы настоятельно рекомендовал вам не использовать числовые индексы! Это делает ваш код более хрупким, а также более сложным для понимания и поддержки: как только изменяется логический порядок столбца, вам необходимо соответствующим образом адаптировать свой код, возможно, в нескольких местах (и вы можете легко контролировать один из них, что к ошибкам). Если вместо этого вы используете имена столбцов или DataColumn сами объекты для поиска, вы можете изменить порядок столбцов без необходимости изменять оставшийся код.

2 голосов
/ 13 апреля 2010

Факты

  1. Получение столбца по индексу является прямым индексом в ArrayList
  2. Если поиск имени чувствителен к регистру, выполняется поиск по хеш-таблице
  3. Если поиск имени не чувствителен к регистру, тогда список сканируется на наличие имени и выполняется более дорогостоящее сравнение строк с учетом локали.

Так что, безусловно, поиск по индексу будет наиболее эффективным, но имеет ли это значение?

Выполняя некоторые базовые (чтение наивные) тесты на моей машине, я обнаружил, что 1 000 000 обращений к столбцу с использованием упомянутого механизма индексации занимают следующие времена

  1. Прямой индекс - 13,3 мс
  2. Поиск без учета регистра - 109,11 мс
  3. Поиск с учетом регистра - 109,24 мс

Таким образом, в зависимости от вашего сценария вы можете сделать свои выводы.

1 голос
/ 13 апреля 2010

Лучший подход - найти индекс по имени столбца и использовать индекс для определения местоположения столбца:

Dim table As DataTable = ...

Dim foo As int = table.Columns("Foo")

For Each row As DataRow In table.Rows

    Dim data = row(foo)

Next

Вы просматриваете по индексу, а также по названию можете угадать, какой столбец вы читаете. Другое преимущество заключается в том, что если вы измените порядок полей в запросе выбора, вы все равно получите правильное значение. С другой стороны, если вы жестко кодируете индексы, ваш код сломается.

1 голос
/ 13 апреля 2010

Да, есть затраты на поиск столбца по имени, а не по абсолютному индексу (так как он просто находит столбец, а затем обращается к нему таким образом).

Это, как говорится, довольно преждевременная оптимизация. DataTable сначала попытается найти столбец с учетом регистра , что очень быстро. Если он не может найти столбец таким образом, он выглядит без учета регистра , что лишь немного медленнее.

Абсолютно самый быстрый способ доступа к данным - через сам объект DataColumn, так как его используют как средства доступа на основе индекса, так и на основе имени.

0 голосов
/ 14 апреля 2010

Зависит от того, где вы его используете. При запуске приложений для настольных компьютеров такие небольшие недостатки могут накапливаться с большими задержками. На событиях мыши и клавиатуры скорее всего нет. Скорее всего, будет более эффективно тратить время на профилирование функций (вывод времени выполнения в dbgview), чем на оптимизацию такого рода низкоуровневых вещей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...