ResultSet: получение значений столбца по индексу по сравнению с извлечением по метке - PullRequest
49 голосов
/ 09 октября 2008

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

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

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

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

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

Ответы [ 13 ]

56 голосов
/ 09 октября 2008

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

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

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

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

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

45 голосов
/ 09 октября 2008

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

Плюсы:

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

Минусы:

  • Вы не можете управлять именами столбцов (доступ с помощью хранимых процедур)

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

Интс

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

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

6 голосов
/ 04 февраля 2010

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

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

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

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

5 голосов
/ 26 июня 2013

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

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

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

4 голосов
/ 04 февраля 2010

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

Спасибо

2 голосов
/ 29 ноября 2010

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

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

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

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

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

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

2 голосов
/ 31 декабря 2008

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

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

2 голосов
/ 09 октября 2008

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

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

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

1 голос
/ 09 октября 2008

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

0 голосов
/ 15 апреля 2019

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

...