Първо, важно е да се прави разлика между клиентски и сървърни подготвени оператори.
Подготвени от клиента изявления
Подготвените от клиента изявления са "емулирани" подготвени изявления. Това означава, че низът на SQL инструкция е токенизиран от страна на клиента и всички заместители се заменят с литерални стойности, преди да се изпрати изразът на сървъра за изпълнение. Пълен SQL оператор се изпраща на сървъра при всяко изпълнение. Можете да използвате общия дневник, за да проучите как работи това. напр.
следния код:
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()
ще се покаже в дневника:
255 Query select 42
255 Query select 43
"Заявката" показва, че на ниво протокол COM_QUERY
командата се изпраща със следния низ на оператора.
Подготвени от сървъра изявления
Подготвените от сървъра оператори са "истински" подготвени оператори, което означава, че текстът на заявката се изпраща на сървъра, анализира се и информацията за място и резултатът се връща на клиента. Това получавате, когато задавате useServerPrepStmts=true
. Низът на оператора се изпраща на сървъра само веднъж с COM_STMT_PREPARE
обадете се (документирано тук
). Всяко изпълнение се извършва чрез изпращане на COM_STMT_EXECUTE
с подготвения манипулатор на оператора и литералните стойности, които да заменят заместващите.
За контраст с примера, подготвен от клиента, можем да използваме подобен блок код (но този път с активирани изрази, подготвени от сървъра):
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()
И дневникът ще покаже:
254 Prepare select ?
254 Execute select 42
254 Execute select 43
Можете да видите, че изявлението е подготвено преди да бъде изпълнено. Регистраторът ни прави услуга и показва пълния оператор за изпълнението, но всъщност само стойностите за място се изпращат от клиент на сървър за всяко изпълнение.
Кеширане на подготвени изявления
Много пулове за връзки ще кешират подготвени оператори при използване на връзка, което означава, че ако извикате conn.prepareStatement("select ?")
, той ще върне същия PreparedStatement
екземпляр при последователни извиквания със същия низ от оператори. Това е полезно, за да се избегне подготвянето на един и същ низ на сървъра многократно, когато връзките се връщат към пула между транзакциите.
Опцията MySQL JDBC cachePrepStmts
ще кешира подготвените оператори по този начин (както клиентски, така и сървърни подготвени оператори), както и ще кешира "подготвимостта" на изявление. Има някои изявления в MySQL, които не могат да се подготвят от страна на сървъра. Драйверът ще се опита да подготви изявление на сървъра, ако смята, че е възможно и, ако подготовката не успее, ще се върне към подготвен от клиента оператор. Тази проверка е скъпа поради изискване за двупосочно пътуване до сървъра. Опцията също ще кешира резултата от тази проверка.
Надявам се това да помогне.