2008-10-09 5 views
43

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

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

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

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

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

+0

Есть ли константы для его использования? Что-то вроде «ResultSet.CUSTOMER_ID» – EliuX 2015-02-18 18:05:15

ответ

39

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

Плюсы:

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

Минусы:

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

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

ints?

int i = 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 есть новый столбец? Какой код вы предпочитаете? Или, если порядок столбцов изменен, какую версию кода вам нужно изменить вообще?

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

1

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

51

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

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

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

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

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

2

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

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

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

+2

См. Ваш вопрос, но я не думаю, что это действительно так помогает. int COLUMN_FIRST_NAME = 13; int COLUMN_SURNAME = 14; может быть ошибка; Maye FIRST name равно 14, а FURNAME - 13. И вам все равно придется настраивать, когда столбцы добавляются и т. д. Если вы должны использовать константы, я бы использовал Strings, чтобы избежать этого. – Cowan 2008-10-09 11:38:47

+0

int константы решают проблему читаемости, но в предыдущем комментарии подчеркивается, что проблема гибкости остается. Я также предпочел бы строковые константы. Но я не использовал константы в примерах, считая, что это сделает мою точку более ясной. – Rorick 2008-10-09 12:02:23

0

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

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

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

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

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

0

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

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

2

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

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

4

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

Благодаря

6

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

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

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

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

1

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

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

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

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

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

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

4

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

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

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

Смежные вопросы