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

Подготовленные материалы и производительность

Поэтому я продолжаю слышать, что PreparedStatements хороши для производительности.

У нас есть приложение Java, в котором мы используем регулярное "Statement" больше, чем мы используем "PreparedStatement". При попытке перейти к использованию более PreparedStatements, я пытаюсь получить более полное представление о том, как работают PreparedStatements - на стороне клиента и на стороне сервера.

Итак, если у нас есть некоторые типичные операции CRUD и многократно обновлять объект в приложении, помогает ли это использовать PS? Я понимаю, что нам придется закрывать PS каждый раз, в противном случае это приведет к утечке курсора.

Итак, как это помогает в производительности? Является ли драйвер кэшем предварительно скомпилированный оператор и дает мне копию при следующем подключении connection.prepareStatement? Или сервер БД помогает?

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

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

    // some code blah blah
    update();

    // some more code blah blah 
    update();

.... 

public void update () throws SQLException{
 try{
      PreparedStatement ps = connection.prepareStatement("some sql");
      ps.setString(1, "foobar1");
      ps.setString(2, "foobar2");
      ps.execute();
 }finally {
     ps.close();

 }

}

Невозможно на самом деле повторно использовать java-объект ps, и я понимаю, что фактический вызов connection.prepareStatement довольно дорог.

Вот что возвращает меня к первоначальному вопросу. Это "некоторые sql" PreparedStatement все еще кэшируются и повторно используются под обложками, о которых я не знаю?

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

Спасибо заранее.

4b9b3361

Ответ 1

Понятие о том, что подготовленные заявления в основном относится к производительности, является чем-то неправильным, хотя оно довольно распространенное.

В другом плакате упоминается, что он отметил улучшение скорости около 20% в Oracle и SQL Server. Я отметил аналогичную цифру с MySQL. Оказывается, что разбор запроса просто не является такой значительной частью работы. В очень загруженной системе баз данных также неясно, что разбор запросов влияет на общую пропускную способность: в целом, вероятно, это просто будет использовать процессорное время, которое в противном случае было бы бездействующим, когда данные возвращались с диска.

В качестве причины для использования подготовленных операторов защита защиты от SQL-инъекций намного превосходит улучшение производительности. И если вас не беспокоят атаки SQL-инъекций, вы, вероятно, должны быть...

Ответ 2

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

PreparedStatement ps = connection.prepare("SOME SQL");

for (Data data : dataList) {
  ps.setInt(1, data.getId());
  ps.setString(2, data.getValue();
  ps.executeUpdate();
}

ps.close();

Это намного быстрее, чем создание инструкции в цикле.

Некоторые платформы также кэшируют подготовленные операторы, поэтому даже если вы их закрываете, их можно быстрее восстановить.

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

Ответ 3

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

Более подробную информацию можно найти здесь:

http://www.theserverside.com/tt/articles/article.tss?l=Prepared-Statments

и вы можете посмотреть на Spring JDBCTemplate как альтернативу прямому использованию JDBC.

http://static.springframework.org/spring/docs/2.0.x/reference/jdbc.html

Ответ 4

Разбор SQL - это не единственное, что происходит. Там проверяется, что таблицы и столбцы действительно существуют, создавая план запроса и т.д. Вы платите это один раз с помощью PreparedStatement.

Привязка для защиты от SQL-инъекций - это очень хорошо. Недостаточно, ИМО. Вы все равно должны проверять ввод до перехода к уровню сохранения.

Ответ 5

Итак, как это помогает в производительности? Включает ли драйвер кеш предварительно скомпилированный отчет и дайте мне копию в следующий раз connection.prepareStatement? Или сервер БД помогает?

Я отвечу с точки зрения производительности. Другие здесь уже заявили, что PreparedStatement устойчивы к SQL-инъекции (благословенное преимущество).

Приложение (Драйвер JDBC) создает PreparedStatement и передает его в СУБД с помощью заполнителей (?). RDBMS прекомпилирует, применяя оптимизацию запроса (при необходимости) полученного PreparedStatement и (в некоторых), как правило, кэширует их. Во время выполнения PreparedStatement используется предварительно скомпилированный PreparedStatement, заменяя каждый заполнитель соответствующими значениями и рассчитывается. Это контрастирует с Statement, который компилирует его и выполняет его непосредственно, PreparedStatement компилирует и оптимизирует запрос только один раз. Теперь этот сценарий, описанный выше, не является абсолютным случаем для всех поставщиков JDBC, но по существу, как PreparedStatement используются и работают.

Ответ 6

Анекдотично: несколько лет назад я провел несколько экспериментов с подготовленными или динамическими операторами, использующими ODBC в Java 1.4, как с Oracle, так и с SQL Server. Я обнаружил, что подготовленные заявления могут быть на 20% быстрее для определенных запросов, но существуют различия в отношении поставщиков, в отношении которых запросы были улучшены в какой степени. (На самом деле это не удивительно.)

Суть в том, что если вы будете повторно использовать один и тот же запрос повторно, подготовленные операторы могут помочь повысить производительность; но если ваша производительность настолько плоха, что вам нужно что-то сделать с этим немедленно, не рассчитывайте на использование подготовленных заявлений, чтобы дать вам радикальный импульс. (20% обычно нечего писать домой.)

Ваш пробег может варьироваться, конечно.

Ответ 7

Вот что возвращает меня к первоначальному вопросу. Это "некоторые sql" PreparedStatement все еще кэшируются и повторно используются под обложками, о которых я не знаю?

Да, по крайней мере, с Oracle. Руководство разработчика для JDBC для Oracle® Неявное кэширование выписок (выделено мной),

Когда вы включаете неявное кэширование Statement, JDBC автоматически кэширует подготовленный или вызываемый оператор, когда вы вызываете метод close этого объекта-оператора. Подготовленные и вызываемые операторы кэшируются и извлекаются с использованием стандартных объектов соединения и методов объекта-оператора.

Обычные заявления неявно кэшируются, потому что неявное кэширование Statement использует строку SQL в качестве ключа, а простые инструкции создаются без строки SQL. Поэтому неявное кэширование Statement применяется только к объектам OraclePreparedStatement и OracleCallableStatement, которые создаются с помощью строки SQL. Вы не можете использовать неявное кэширование Statement с OracleStatement. Когда вы создаете OraclePreparedStatement или OracleCallableStatement, драйвер JDBC автоматически выполняет поиск в кеше для соответствующего оператора.

Ответ 8

1. PreparedStatement позволяет вам писать динамический и параметрический запрос

Используя PreparedStatement в Java, вы можете писать параметризованные sql-запросы и отправлять разные параметры, используя те же SQL-запросы, которые намного лучше, чем создание разных запросов.

2. PreparedStatement быстрее, чем Statement в Java

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

3. PreparedStatement предотвращает атаки SQL Injection в Java

Подробнее: http://javarevisited.blogspot.com/2012/03/why-use-preparedstatement-in-java-jdbc.html#ixzz3LejuMnVL

Ответ 9

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

В качестве примера, с точки зрения производительности базы данных, база данных Oracle кэширует план выполнения некоторых запросов после каждого вычисления (это неверно для всех версий и всей конфигурации Oracle). Вы можете найти улучшения, даже если закрыть выражение и открыть новый, потому что это делается на уровне РСУБД. Этот тип кеширования активируется, только если два последующих запроса (char -by- char) одинаковы. Это не относится к нормальным операторам, поскольку параметры являются частью запроса и производят разные строки SQL.

Некоторые другие СУБД могут быть более "интеллектуальными", но я не ожидаю, что они будут использовать сложные алгоритмы сопоставления образцов для кэширования планов выполнения, поскольку это снизит производительность. Вы можете утверждать, что вычисление плана выполнения является лишь небольшой частью выполнения запроса. В общем случае я согласен, но... это зависит. Имейте в виду, что, как правило, вычисление плана выполнения может быть дорогостоящей задачей, потому что rdbms необходимо проконсультироваться с данными вне памяти, такими как статистика (а не только Oracle).

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

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

Ответ 10

Короткий ответ:

PreparedStatement помогает производительности, потому что обычно клиенты БД выполняют один и тот же запрос повторно, и это позволяет выполнять предварительную обработку для исходного запроса , чтобы ускорить следующие повторяющиеся запросы.

Длинный ответ:

Согласно Wikipedia, типичный рабочий процесс с использованием подготовленного оператора выглядит следующим образом:

Подготовить: шаблон заявления создается приложением и отправляется к системе управления базами данных (СУБД). Определенные значения остаются неопределенные, называемые параметрами, заполнителями или связующими переменными (обозначается "?" ниже): ВСТАВИТЬ В ПРОДУКТ (имя, цена) ЦЕННОСТИ (?,?)

(предварительная компиляция): СУБД анализирует, компилирует и выполняет оптимизацию запросов на шаблон заявки и сохраняет результат без его выполнения.

Выполнить: позднее приложение добавляет (или связывает) значения для параметров, и СУБД выполняет инструкцию (возможно возвращая результат). Приложение может выполнять инструкцию как многие раз, когда он хочет иметь разные значения. В этом примере это могло бы поставьте "Хлеб" для первого параметра и "1.00" для второго Параметр.

Подготовка:

В JDBC шаг "Подготовить" выполняется путем вызова java.sql.Connection. prepareStatement (String sql) API. Согласно его Джавадоку:

Этот метод оптимизирован для обработки параметрических операторов SQL, которые выигрывают от предварительной компиляции. Если драйвер поддерживает предварительную компиляцию, метод prepareStatement отправит инструкцию в базу данных для предварительной компиляции. Некоторые драйверы могут не поддерживать предварительную компиляцию. В этом случае оператор не может быть отправлен в базу данных до тех пор, пока не будет выполнен объект PreparedStatement. Это не оказывает прямого влияния на пользователей; однако он влияет на то, какие методы бросают определенные объекты SQLException.

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

Прекомпиляция:

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

Execute:

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

Вывод:

С точки зрения производительности, использование инструкции подготовки является двухфазным процессом:

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

И если вы хотите узнать более подробную информацию, есть некоторые статьи, объясняющие преимущества PrepareStatement: