Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Плюсы:

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

Минусы:

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

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

Интс?

int я = 1;
 customerId = resultSet.getInt(i ++);
 customerName = resultSet.getString(i ++);
 customerAddress = resultSet.getString(i ++);

или строки?

customerId = resultSet.getInt( "customer_id" );
 customerName = resultSet.getString( "customer_name" );
 customerAddress = resultSet.getString( "customer_address" );

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

Для этого вам следует использовать строковые метки по умолчанию.

Ответ 2

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

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

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

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

* Изображение составлено.

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

Спасибо

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 8

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

Сначала - если вы не зацикливаете через результирующий набор, просто используйте имена столбцов.

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

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

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

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

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

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

Ответ 12

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

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

Ответ 13

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