2015-03-25 6 views
0

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

Если вы отправляете новое, полное заявление SQL для каждого запроса или обновления для базы данных, база данных должна анализировать SQL и запросов создать план запроса. Повторно используя существующее PreparedStatement, вы можете повторно использовать как анализ SQL-запросов, так и план запросов для последующих запросов. Этот ускоряет выполнение запроса, уменьшая синтаксический анализ и запрос накладные расходы на планирование каждого исполнения.

Скажем, я создаю заявление и предоставляя различные значения во время выполнения запросов, как это:

String sql = "update people set firstname=? , lastname=? where id=?"; 

PreparedStatement preparedStatement = 
     connection.prepareStatement(sql); 

preparedStatement.setString(1, "Gary"); 
preparedStatement.setString(2, "Larson"); 
preparedStatement.setLong (3, 123); 

int rowsAffected = preparedStatement.executeUpdate(); 

preparedStatement.setString(1, "Stan"); 
preparedStatement.setString(2, "Lee"); 
preparedStatement.setLong (3, 456); 

int rowsAffected = preparedStatement.executeUpdate(); 

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

Не могли бы вы объяснить, когда мы получим выгоду от производительности? Должны ли значения быть одинаковыми?

ответ

4

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

Обычно вы используете подготовленный оператор с переменными привязки, где вы указываете переменные во время выполнения. Теперь, что происходит для последовательного выполнения подготовленных операторов, вы можете указать переменные, которые отличаются от предыдущих вызовов. С точки зрения БД, ему не нужно каждый раз составлять инструкцию, просто вставлять переменные связывания во время rum. Так становится быстрее.

Другие преимущества подготовленных заявлений является его защита от SQL-инъекции нападение

Так значения не должны быть одинаковыми

+0

Точнее, Oracle необходимо выполнить «мягкий» синтаксический анализ, то есть поиск из кеша курсора, вместо «жесткого» анализа (что дорого) в следующий раз, когда он сталкивается с тем же самым заявлением. –

0

Хотя это не очевидно, SQL не сценариев, но «составлен» язык. И эта компиляция ака. Оптимизация aka hard-parse - очень сложная задача. Oracle должен много работать, он должен анализировать запрос, разрешать имена таблиц, проверять права доступа, выполнять некоторые алгебраические преобразования, а затем искать эффективный план выполнения. Oracle (и другие базы данных тоже) могут присоединиться только к двум таблицам - не более. Это означает, что тогда, когда вы присоединяетесь к нескольким таблицам в SQL, Oracle должен присоединиться к ним один за другим. т. е. если вы присоедините n таблиц в запросе, возможно, по крайней мере до n! возможных планов выполнения. По умолчанию Oracle ограничивается до 8000 перестановок при поиске «оптимального» (не самого лучшего) плана выполнения.

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

С другой стороны, бывают ситуации, когда переменные связывания НЕ полезны. Представьте, такой запрос:

update people set firstname=? , lastname=? where group=? and deleted='N' 

Поскольку столбец deleted индексируется и Oracle знает, что есть 98% «Y» значений = и только 2% от значений = «N», она будет выводить использовать и индекс в колонке deleted. Если вы использовали переменную связывания для условия на deleted, то столбец Oracle не смог найти эффективный план выполнения, поскольку он также зависит от ввода, который неизвестен во время компиляции. (PS: с 11 г сложнее с переменным зависанием)

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