Gilean's answer è ottimo, ma volevo solo aggiungere che a volte ci sono rare eccezioni alle migliori pratiche e si potrebbe voler testare il proprio ambiente in entrambi i modi per vedere cosa funzionerà meglio.
In un caso, ho scoperto che query
lavorato più veloce per i miei scopi, perché ero di massa il trasferimento dei dati di fiducia da una casella di Ubuntu Linux in esecuzione PHP7 con il mal supportato Microsoft ODBC driver for MS SQL Server.
Sono arrivato a questa domanda perché avevo uno script in esecuzione lungo per uno ETL che stavo cercando di spremere per la velocità. Mi è sembrato intuitivo che query
potesse essere più veloce di prepare
& execute
perché chiamava solo una funzione anziché due. L'operazione di associazione dei parametri fornisce una protezione eccellente, ma potrebbe essere costosa ed eventualmente evitata se non necessaria.
determinate condizioni un paio rari:
Se non è possibile riutilizzare una dichiarazione preparata perché it's not supported by the Microsoft ODBC driver.
Se non si è preoccupati di disinfettare l'input e la semplice escaping è accettabile. Questo potrebbe essere il caso binding certain datatypes isn't supported by the Microsoft ODBC driver.
PDO::lastInsertId
non è supportato dal driver Microsoft ODBC.
Ecco un metodo che ho usato per testare il mio ambiente, e, auspicabilmente, si può replicare o qualcosa di meglio nella vostra:
Per iniziare, ho creato una tabella di base in Microsoft SQL Server
CREATE TABLE performancetest (
sid INT IDENTITY PRIMARY KEY,
id INT,
val VARCHAR(100)
);
E ora un test temporizzato di base per le misurazioni delle prestazioni.
$logs = [];
$test = function (String $type, Int $count = 3000) use ($pdo, &$logs) {
$start = microtime(true);
$i = 0;
while ($i < $count) {
$sql = "INSERT INTO performancetest (id, val) OUTPUT INSERTED.sid VALUES ($i,'value $i')";
if ($type === 'query') {
$smt = $pdo->query($sql);
} else {
$smt = $pdo->prepare($sql);
$smt ->execute();
}
$sid = $smt->fetch(PDO::FETCH_ASSOC)['sid'];
$i++;
}
$total = (microtime(true) - $start);
$logs[$type] []= $total;
echo "$total $type\n";
};
$trials = 15;
$i = 0;
while ($i < $trials) {
if (random_int(0,1) === 0) {
$test('query');
} else {
$test('prepare');
}
$i++;
}
foreach ($logs as $type => $log) {
$total = 0;
foreach ($log as $record) {
$total += $record;
}
$count = count($log);
echo "($count) $type Average: ".$total/$count.PHP_EOL;
}
Ho giocato con più sperimentazione e conta diversi nel mio ambiente specifico, e costantemente ottenere tra il 20-30% risultati più veloci con query
di prepare
/execute
5,8128969669342 preparare
5,8688418865204 preparano
4.2948560714722 query
4.9533629417419 query
5.9051351547241 preparare
4,2060318 interrogazione
5,9672858715057 preparare
5,0667371749878 interrogazione
3,8260300159454 interrogazione
4,0791549682617 interrogazione
4,3775160312653 interrogazione
3,6910600662231 interrogazione
5,2708210945129 preparare
6,2671611309052 preparare
7,3791449069977 preparare
(7) preparare media: 6,0673267160143
(8) interrogare A verage: 4.3276024162769
Sono curioso di vedere come questo test viene confrontato in altri ambienti, come MySQL.
Il collegamento conduce alla domanda con una risposta abbastanza stupida, già criticata nei commenti. –
Quindi, se si utilizza una preparazione in ': calorie 'è quel tipo di equivalente di' mysql_real_escape_string() 'per interrompere le iniezioni o è necessario più di un semplice' $ sth-> bindParam (': calorie ', $ calorie) ; per aumentare la sicurezza? – Dan
Perché 'query' restituisce un * PDOStatement *, invece di un * bool * come' execute'? – Leo