Несколько подготовленных операторов или пакет

Мой вопрос очень простой и в заголовке. Google и переполнение стека ничего мне не дают, поэтому я решил, что пришло время задать вопрос.

В настоящее время я делаю sql-запрос, когда пользователи регистрируются на моем сайте. Я ВСЕГДА использовал только подготовленные операторы из-за дополнительного кодирования в вызываемых операторах, и производительность обычных операторов снижается. Однако этот запрос заставляет меня думать о возможных альтернативах моему предыдущему универсальному способу (подготовленные заявления).

Этот запрос имеет в общей сложности 4 обращения к базе данных туда и обратно. Шаги

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

Кроме того: для всех, кто интересуется тем, как я получаю ключи обратно после вставки, это с Statement.RETURN_GENERATED_KEYS, и вы можете прочитать отличную статью об этом здесь - Статья IBM

В любом случае, я хотел бы знать, допустимо ли использование 4-х (но кэшируемых) подготовленных операторов туда и обратно или мне следует использовать пакетные (но не кэшируемые) операторы?


person gmustudent    schedule 13.03.2013    source источник


Ответы (3)


Пакетные операторы JDBC позволяют уменьшить количество циклов обработки при условии, что между вставляемыми или обновляемыми строками нет зависимости данных. В вашем сценарии это условие не выполняется, поскольку изменения зависят от данных друг друга: операторы со 2 по 4 должны получить идентификатор из предыдущего оператора с 1 по 3.

С другой стороны, четыре круговых поездки определенно неоптимальны. Вот почему такие сценарии, как ваш, требуют хранимых процедур: вы можете поместить всю эту логику в create_user_proc и вернуть идентификатор пользователя обратно вызывающей стороне. Все вставки с 1 по 4 будут происходить внутри вашего кода SQL, что позволит вам управлять зависимостями идентификаторов в SQL. Вы могли бы вызвать эту хранимую процедуру за одно обращение, что определенно быстрее, особенно если вы обрабатываете несколько регистраций пользователей в минуту.

person Sergey Kalinichenko    schedule 13.03.2013
comment
Спасибо. Я приму твой совет. У вас случайно нет ссылки, где я могу получить некоторые инструкции о том, что вы говорите мне делать? Особенно как получить сгенерированный ключ и перейти к следующей таблице? Я использую mysql. - person gmustudent; 13.03.2013
comment
И следует ли вам почти всегда использовать хранимые процедуры исключительно с точки зрения производительности? Разве это не всегда будет быстрее, чем подготовленные операторы или обычные операторы? - person gmustudent; 13.03.2013
comment
@gmustudent Вы можете узнать о хранимых процедурах в MySQL, просмотрев учебные пособия здесь. Синтаксис не такой сложный - в вашем случае у вас будет четыре вставки и используйте last_inserted_id(). - person Sergey Kalinichenko; 13.03.2013
comment
@gmustudent Помимо чисто производительных соображений, предлагаемых за счет сокращения количества обращений туда и обратно, хранимые процедуры позволяют перенести логику обработки и извлечения данных на сторону СУБД. Однако использование SP для инкапсуляции логики является вопросом предпочтения. - person Sergey Kalinichenko; 13.03.2013
comment
@dasblinkenlight вы ошибаетесь в своем первом предположении. Все вставки/обновления не работают только с одной таблицей. Код Statement stmt1 = connection.createStatement(); addBatch("insert into one_table values (1)"); addBatch("insert into some_other_table values (2)"); executeBatch(); правильно показывает 130524 10:59:09 15087 Query insert into one_table values (1);insert into some_other_table values (2) в журнале запросов. - person Andreas Wederbrand; 24.05.2013
comment
@AndreasWederbrand Приятно знать. Я почти уверен, что столкнулся с первым ограничением некоторое время назад, но я не могу вспомнить, когда и какой драйвер это был (я был вне мира Java уже более 5 лет). Спасибо за информацию! - person Sergey Kalinichenko; 24.05.2013

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

person ajduke    schedule 13.03.2013

Я согласен с dasblinkenlight и ajduke, чтобы повысить производительность и сократить количество обращений к базе данных — этого можно добиться с помощью хранимых процедур.

Но действительно ли это узкое место в производительности вашего приложения?

  • Как часто пользователи регистрируются на вашем сайте?
  • Сравните это с тем, как часто информация читается из этих таблиц (один раз за доступ к странице?)

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

Почему вы можете не захотеть использовать хранимые процедуры и придерживаться подготовленных операторов:

  • не так переносим, ​​как использование подготовленных операторов (разный синтаксис/язык для каждой базы данных, некоторые более простые базы данных даже не поддерживают их)
  • не будет работать с решениями ORM, такими как JPA * - вы упомянули об использовании PreparedStatements напрямую, так что это, вероятно, не относится к вам, по крайней мере, не сейчас, но это может ограничить вас позже, если вы захотите использовать ORM в будущем

* JPA 2.1 на самом деле может поддерживать хранимые процедуры, но на момент написания он еще не выпущен .

person prunge    schedule 13.03.2013
comment
Отличная отличная информация. Спасибо - person gmustudent; 13.03.2013