2010-01-20 6 views
24

Я знаю, преимущество использования PreparedStatement, которыеКогда мы должны использовать PreparedStatement вместо Statement?

  • запроса переписываются и компилируется сервер базы данных
  • защиты от инъекции SQL

Но я хочу знать, когда мы используем его вместо от Statement?

+0

возможно дубликат [PreparedStatements и производительность] (http://stackoverflow.com/questions/687550/preparedstatements-and-performance) – sarnold

ответ

25
  1. запрос переписывается и компилируется сервером базы данных

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

  2. Защита от инъекции SQL

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

9

Я бы превратить этот раунд: в публично распределенном приложении, вы должны, как правило всегда использовать подготовленные заявления , если у вас есть действительно веские причины не, и вы всегда должны поставить параметры «правильно» в подготовленный оператор, а не путем объединения их в строку запроса.

Почему? Ну, в основном из-за причин, по которым вы дали (или, по крайней мере, второй) ...

+3

Примечание: Производительность в PreparedStatement может быть плачевны, если вы делаете _lots_ операций с ним , Это зависит от драйвера базы данных. –

+0

Спасибо, это интересный момент.Из интереса, у вас есть пример конкретного DB/драйвера, где это так? Из тестов, которые я сделал с MySQL, в нем нет ничего по производительности. Не просто помните с SQL Server, хотя не помните, что подготовленные заявления были особенно плохими. –

0

Помимо предотвращения внедрения SQL, форматирование переносимости (которое вы не можете получить от Statement), производительность является очевидной причиной. Однако PreparedStatement не начисляется штраф. Например, он работает медленнее, чем Statement, если работает только один раз, так как есть некоторые накладные расходы. Поэтому общая идея PreparedStatement должна использоваться, когда вы выполняете один и тот же запрос много раз.Однако, сколько накладных расходов является очень специфичным для сервера баз данных, поэтому точно, когда выбирать PreparedStatement по сравнению с Statement, с точки зрения эффективности, действительно должно быть основано на вашем фактическом опыте/опыте конкретного сервера базы данных.

16

Спросите Тома opinion:

Использование Заявление в JDBC должно быть 100% локализуется используется для DDL (ALTER, CREATE, GRANT, и т.д.), поскольку они являются единственными типами заявление, что не может принять BIND VARIABLES ,

Подготовленные элементы или CallableStatements должны использоваться для КАЖДОГО ДРУГОГО типа оператора (DML, Queries). Поскольку это типы операторов, которые принимают переменные связывания.

Это факт, правило, законное использование готовых заявлений ВЕЗДЕ. Используйте ЗАЯВЛЕНИЯ практически нет.

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

Приложения баз данных, которые масштабируют и предотвращают атаки SQL-инъекций одновременно. Какая минута?

5

Подготовленные материалы должны быть очень тщательно использованы в предложениях WHERE.

Предположим, что таблица определяется как:

create table t (int o, k varchar(100), v varchar(100)) 

(например, "O: ID объекта (внешний ключ), к: атрибут ключа, v: атрибут-значение"). .

Кроме того, существует (не уникальный) индекс V

create index ixt on t (v) 

Предположим, что эта таблица содержит 200 миллионов строк, вставленные как:

for (i = 0; i < 100*1000*1000; i++) { 
    insert into t (o,k,v) values (i,'k1','v1'); 
    insert into t (o,k,v) values (i,'k2', Convert(i, varchar)); 
} 

("Таким образом, каждый объект О имеет атрибуты k1 = v1 и k2 = o ")

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

select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k=? and tx.v=? and ty.k=? and ty.v=? 

(«найти объекты, которые имеют две заданные атрибуты»)

Мой опыт работы с ORACLE и MSSQL в том, что эти запросы может понадобиться много минут вернуться. Это верно, даже если ни одна строка не соответствует предложению where. Это зависит от того, как SQL-Server решает сначала искать tx.v или ty.v.

Один shoud помещает значения для столбцов k и v directy в оператор. Я думаю, это связано с тем, что SQL-серверы учитывают значения при вычислении плана выполнения.

Взгляд запрос, как это всегда возвращает после миллисекунд:

select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k='k1' and tx.v='v1' and ty.k='k2' and ty.v='1234' 

("The SQL-Server всегда будет искать первую для V = '1234', а затем для V = 'v1'")

с уважением
Вольфганг

1

Я предпочитаю Использовать PreparedStatement, если я хочу, чтобы выполнить запрос. (Вставить, Выбрать, ... и т. Д.). Тот же разозон, что и другим, написанным выше.

Но если мне нужно использовать динамический paramters я использую просто заявление потому что я могу Исло строить свою строку SQL thhan просто выполнить. (inmyopinion) Если вы хотите построить динамический запрос с помощью подготовленногоStatment, у вас будет огромный код спагетти, который никто не понимает.

+1

Вы предпочитаете, но это худший способ сделать. Преимущества PreparedStatement находятся в динамических параметрах. – amdev

+0

Я имею в виду динамическое число параметров. Не значение параметров динамическое ... – Csanesz

+1

Насколько я понимаю, я думаю, что вы должны сохранить свой динамический параметр на карте при построении динамического запроса. Но это утомительно. – amdev

0

Заявление: Каждый раз, когда выполняется запрос sql, этот оператор sql отправляется в СУБД, где он скомпилирован. Таким образом, он увеличивает нагрузку на сервер и снижает производительность.

connection con=null; 
    String sql="select * from employee where id=5"; 
Statement st=conn.createStatement(); 

PreparedStatement: В отличие от PreparedStatement Заявление дается запрос SQL в качестве параметра при его создании.

connection con=null; 
String sql="select * from employee where id=?"; 
PreparedStatement ps=conn.prepareStatement(sql); 

Этот оператор sql отправляется в базу данных, где он скомпилирован. Итак, в readyStatement скомпилировано происходит только один раз, но в скомпилированном выражении происходит каждый раз, когда вызывается Statement.

0

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

Но, не используйте его с динамическим подобным запросом, запросом с WHERE variable IN [ hundreds possibilities ]:

  1. Это Contre-продуктивное, вы потеряли работоспособность и память, потому что вы кэшировать каждый раз, когда новый запрос, и PreparedStatement является не только для SQL-инъекций, но и для производительности. В этом случае Statement не будет медленнее.

  2. Ваш пул имеет префикс PreparedStatment (-1 defaut, но вы должны его ограничить), и вы достигнете этого предела! и если у вас нет предела или очень большого предела, у вас есть некоторый риск утечки памяти и в крайнем случае ошибки OutofMemory. Так что если это для вашего небольшого индивидуального проекта, используемого тремя пользователями, это не драматично, но вы не хотите, чтобы, если вы в большой компании и что вы используете приложение, используется тысячами людей и миллионным запросом.

Некоторые чтения. IBM : Memory utilization considerations when using prepared statement caching

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