Результирующий набор:Извлечение значений столбца по индексу в сравнении с извлечением по метке

StackOverflow https://stackoverflow.com/questions/186799

Вопрос

При использовании JDBC я часто сталкиваюсь с такими конструкциями, как

ResultSet rs = ps.executeQuery();
while (rs.next()) {
    int id = rs.getInt(1);
    // Some other actions
}

Я спросил себя (и авторов кода тоже), почему бы не использовать метки для извлечения значений столбцов:

int id = rs.getInt("CUSTOMER_ID");

Лучшее объяснение, которое я слышал, - это что-то, касающееся производительности.Но на самом ли деле это делает обработку данных чрезвычайно быстрой?Я в это не верю, хотя я никогда не проводил измерений.Даже если извлечение по метке будет немного медленнее, тем не менее, на мой взгляд, это обеспечит лучшую читабельность и гибкость.
Итак, может ли кто-нибудь дать мне хорошее объяснение, как избежать извлечения значений столбца по индексу столбца вместо метки столбца?Каковы плюсы и минусы обоих подходов (возможно, в отношении определенной СУБД)?

Это было полезно?

Решение

Вы должны использовать строковые метки по умолчанию.

Плюсы:

  • Независимость от порядка следования столбцов
  • Лучшая читабельность / ремонтопригодность

Минусы:

  • У вас нет контроля над именами столбцов (доступ через хранимые процедуры).

Что бы вы предпочли?

целые числа?

int i = 1;
CustomerID = Результирующий набор.getInt(i ++);
Пользовательское имя = ResultSet.getString(i++);
CustomerAddress = Результирующий набор.getString(i ++);

или Струны?

CustomerID = Результирующий набор.getInt("customer_id");
Имя_клиента = ResultSet.getString("имя_клиента");
CustomerAddress = Результирующий набор.getString("customer_address");

А что, если в позицию 1 будет вставлен новый столбец?Какой код вы бы предпочли?Или, если порядок столбцов будет изменен, какую версию кода вам вообще нужно будет изменить?

Вот почему вы должны использовать строковые метки по умолчанию.

Другие советы

Предупреждение: я собираюсь напугаться, потому что это сводит меня с ума.

99% * времени, это смешная микрооптимизация, когда люди имеют смутное представление, что все становится «лучше». Это полностью игнорирует тот факт, что, если вы не будете в чрезвычайно тесном и занятом цикле с миллионами результатов SQL все время , что, как мы надеемся, редко, вы никогда не заметите этого. Для всех, кто этого не делает, затраты времени разработчика на поддержку, обновление и исправление ошибок в индексации столбцов намного превышают дополнительные затраты на оборудование для вашего приложения с чрезвычайно низкой производительностью.

Не кодируйте оптимизации, подобные этой, в коде для человека, который его поддерживает. Затем наблюдайте, измеряйте, анализируйте и оптимизируйте. Наблюдайте снова, измеряйте снова, анализируйте снова и снова оптимизируйте.

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

* Рисунок составлен.

Ответ был принят, тем не менее, вот некоторая дополнительная информация и личный опыт, который я еще не выдвинул.

Используйте имена столбцов (константы, а не литералы предпочтительнее) в общем и по возможности. Это и понятнее, и проще в обслуживании, и будущие изменения с меньшей вероятностью повредят код.

Однако существует использование индексов столбцов. В некоторых случаях это происходит быстрее, но этого недостаточно, чтобы это перекрывало приведенные выше причины имен *. Они очень полезны при разработке инструментов и общих методов, работающих с ResultSet . Наконец, может потребоваться индекс, потому что у столбца нет имени (например, безымянного агрегата) или есть повторяющиеся имена, поэтому нет простого способа ссылаться на оба.

* Обратите внимание, что я написал несколько драйверов JDBC и заглянул внутрь некоторых открытых источников, один, и внутри они используют индексы столбцов для ссылки на столбцы результатов. Во всех случаях, с которыми я работал, внутренний драйвер сначала сопоставляет имя столбца с индексом. Таким образом, вы можете легко увидеть, что имя столбца во всех этих случаях всегда будет занимать больше времени. Это может быть не верно для всех драйверов.

Из документации по Java:

  

Интерфейс ResultSet предоставляет методы получения (getBoolean, getLong и т. д.) для получения значений столбцов из текущей строки. Значения могут быть получены с использованием либо порядкового номера столбца, либо имени столбца. В целом, использование индекса столбца будет более эффективным. Столбцы пронумерованы от 1. Для максимальной переносимости столбцы набора результатов в каждой строке следует читать в порядке слева направо, а каждый столбец следует читать только один раз.

Конечно, каждый метод (именованный или индексированный) имеет свое место. Я согласен, что именованные столбцы должны быть по умолчанию. Однако в тех случаях, когда требуется огромное количество циклов, и когда оператор SELECT определен и поддерживается в одном и том же разделе кода (или класса), индексы должны быть в порядке - желательно перечислить выбранные столбцы, а не просто " SELECT * FROM ... " ;, так как любое изменение таблицы нарушит код.

Несомненно, использование названий столбцов повышает удобочитаемость и упрощает обслуживание.Но использование имен столбцов имеет и обратную сторону.Как вы знаете, SQL допускает несколько имен столбцов с одинаковым именем, нет никакой гарантии, что имя столбца, которое вы ввели в методе getter ResultSet, действительно указывает на имя столбца, к которому вы собираетесь получить доступ.Теоретически предпочтительно использовать индексные номера вместо названий столбцов, но это снижает читабельность...

Спасибо

Я не думаю, что использование меток сильно влияет на производительность. Но есть и другая причина не использовать String . Или int , если на то пошло.

Рассмотрите возможность использования констант. Использование константы int делает код более читабельным, но также снижает вероятность возникновения ошибок.

Помимо того, что она более читабельна, константа также не позволяет вам делать опечатки в именах меток - компилятор выдаст ошибку, если вы это сделаете. И любой IDE, достойный чего-либо, подберет его. Это не тот случай, если вы используете String или ints .

Я провел некоторое профилирование производительности по этому конкретному вопросу в базе данных Oracle. В нашем коде у нас есть ResultSet с множеством столбцов и огромным количеством строк. Из 20 секунд (!) Запрос выполняется для выполнения метода oracle.jdbc.driver.ScrollableResultSet.findColumn (String name) занимает около 4 секунд.

Очевидно, что что-то не так с общим дизайном, но использование индексов вместо имен столбцов, вероятно, заняло бы это 4 секунды.

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

Во-первых, если вы не просматриваете цикл результатов, просто используйте имена столбцов.

<Ол>
  • Определите набор целочисленных переменных, по одной для каждого столбца, к которому вы будете обращаться. Имена переменных могут включать в себя имя столбца: например, iLast_Name.

  • Перед циклом набора результатов выполните итерацию по метаданным столбца и установите значение каждой целочисленной переменной равным индексу столбца соответствующего имени столбца. Если индекс столбца «Last_Name» равен 3, тогда установите значение «iLast_Name» на 3.

  • В цикле набора результатов используйте целочисленные имена переменных в методах GET / SET. Имя переменной является визуальной подсказкой для разработчика / сопровождающего относительно фактического имени столбца, к которому осуществляется доступ, но значение является индексом столбца и даст наилучшую производительность.

  • ПРИМЕЧАНИЕ. Первоначальное сопоставление (то есть сопоставление имени столбца и индекса) выполняется только один раз перед циклом, а не для каждой записи и столбца в цикле.

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

    Я согласен с предыдущими ответами, что производительность - это не то, что может заставить нас выбрать какой-либо из подходов.Вместо этого было бы неплохо рассмотреть следующие вещи:

    • Читаемость кода:для каждого разработчика, читающего ваш код, метки имеют гораздо больше смысла, чем индексы.
    • Техническое обслуживание:подумайте о SQL-запросе и о том, как он поддерживается.Что с большей вероятностью произойдет в вашем случае после исправления / улучшения / рефакторинга SQL-запроса:изменение порядка извлеченных столбцов или изменение имен столбцов результатов.Мне кажется, что изменение порядка извлеченных столбцов (как результатов добавления / удаления новых столбцов в результирующем наборе) имеет большую вероятность.
    • Инкапсуляция:несмотря на выбранный вами способ, попробуйте изолировать код, в котором вы запускаете SQL-запрос и анализируете результирующий набор, в том же компоненте и сделать так, чтобы только этот компонент знал об именах столбцов и их сопоставлении с индексами (если вы решили их использовать).

    Использование индекса - это попытка оптимизации.

    Время, сэкономленное на этом, тратится впустую из-за дополнительных усилий, которые требуются разработчику для поиска необходимых данных, чтобы проверить, будет ли их код работать должным образом после изменений.

    Я думаю, что это наш встроенный инстинкт использовать цифры вместо текста.

    Помимо поиска в Map для меток, это также приводит к дополнительному созданию String. Хотя это будет происходить в стеке, но все равно это сопряжено с затратами.

    Все зависит от индивидуального выбора, и до сегодняшнего дня я использовал только индексы: -)

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top