जवाबों:
query एक मानक एसक्यूएल स्टेटमेंट चलाता है और आपको एसक्यूएल इंजेक्शन और अन्य मुद्दों से बचने के लिए सभी डेटा को ठीक से बचाना पड़ता है।
executeएक तैयार बयान चलाता है जो आपको मापदंडों से बचने या उद्धृत करने की आवश्यकता से बचने के लिए मापदंडों को बांधने की अनुमति देता है। executeयदि आप कई बार क्वेरी दोहरा रहे हैं तो भी बेहतर प्रदर्शन करेंगे। तैयार कथनों का उदाहरण:
$sth = $dbh->prepare('SELECT name, colour, calories FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories);
$sth->bindParam(':colour', $colour);
$sth->execute();
// $calories or $color do not need to be escaped or quoted since the
// data is separated from the query
सबसे अच्छा अभ्यास तैयार बयानों और executeबढ़ी हुई सुरक्षा के साथ रहना है ।
यह भी देखें: क्या SQL इंजेक्शन को रोकने के लिए PDO तैयार किए गए कथन पर्याप्त हैं?
: calories के mysql_real_escape_string()लिए उस तरह का समान है या क्या आपको $sth->bindParam(':calories', $calories);सुरक्षा बढ़ाने के लिए ज़रूरत से ज़्यादा ज़रूरत है ?
queryएक वापसी PDOStatement , एक के बजाय bool की तरह execute?
नहीं, वे समान नहीं हैं। क्लाइंट-साइड से बचने के अलावा, जो प्रदान करता है, सर्वर-साइड पर एक बार तैयार किया गया विवरण संकलित किया जाता है, और फिर प्रत्येक निष्पादन में विभिन्न मापदंडों को पारित किया जा सकता है । जिसका अर्थ है आप कर सकते हैं:
$sth = $db->prepare("SELECT * FROM table WHERE foo = ?");
$sth->execute(array(1));
$results = $sth->fetchAll(PDO::FETCH_ASSOC);
$sth->execute(array(2));
$results = $sth->fetchAll(PDO::FETCH_ASSOC);
वे आम तौर पर आपको एक प्रदर्शन सुधार देंगे, हालांकि छोटे पैमाने पर ध्यान देने योग्य नहीं। तैयार कथनों (MySQL संस्करण) पर अधिक पढ़ें ।
गिलियन का जवाब बहुत अच्छा है, लेकिन मैं सिर्फ यह जोड़ना चाहता था कि कभी-कभी सर्वोत्तम प्रथाओं के लिए दुर्लभ अपवाद होते हैं, और आप अपने पर्यावरण को दोनों तरीकों से देखना चाहते हैं कि सबसे अच्छा काम क्या होगा।
एक मामले में, मैंने पाया कि queryमेरे उद्देश्यों के लिए तेजी से काम किया क्योंकि मैं एमएस SQL सर्वर के लिए खराब समर्थित Microsoft ODBC ड्राइवर के साथ PHP7 चल रहे उबंटू लिनक्स बॉक्स से भरोसेमंद डेटा स्थानांतरित कर रहा था ।
मैं इस सवाल पर पहुंचा क्योंकि मेरे पास एक ईटीएल के लिए एक लंबी चलने वाली स्क्रिप्ट थी जिसे मैं गति के लिए निचोड़ने की कोशिश कर रहा था। यह मेरे लिए सहज ज्ञान युक्त लग रहा था, जो दो की बजाय केवल एक फ़ंक्शन को कॉल कर रहा था और इससे queryअधिक तेज़ हो सकता है । पैरामीटर बाइंडिंग ऑपरेशन उत्कृष्ट सुरक्षा प्रदान करता है, लेकिन यह महंगा हो सकता है और संभवतः अनावश्यक होने से बचा जा सकता है।prepareexecute
कुछ दुर्लभ स्थितियों को देखते हुए :
यदि आप तैयार कथन का पुनः उपयोग नहीं कर सकते क्योंकि यह Microsoft ODBC ड्राइवर द्वारा समर्थित नहीं है ।
यदि आप इनपुट के बारे में चिंतित नहीं हैं तो इनपुट और सरल पलायन स्वीकार्य है। यह मामला हो सकता है क्योंकि कुछ डेटासेट को बाइंड करना Microsoft ODBC ड्राइवर द्वारा समर्थित नहीं है ।
PDO::lastInsertId Microsoft ODBC ड्राइवर द्वारा समर्थित नहीं है।
यहाँ एक तरीका है जो मैंने अपने पर्यावरण का परीक्षण करने के लिए इस्तेमाल किया है, और उम्मीद है कि आप इसे या आपके भीतर कुछ बेहतर कर सकते हैं:
शुरू करने के लिए, मैंने Microsoft SQL सर्वर में एक मूल तालिका बनाई है
CREATE TABLE performancetest (
sid INT IDENTITY PRIMARY KEY,
id INT,
val VARCHAR(100)
);
और अब प्रदर्शन मैट्रिक्स के लिए एक बुनियादी समयबद्ध परीक्षण।
$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;
}
मैंने अपने विशिष्ट वातावरण में कई अलग-अलग परीक्षण किए हैं और मायने रखता है, और लगातार 20-30% queryसे prepare/ के साथ तेजी से परिणाम प्राप्त करते हैंexecute
5.8128969669342 तैयार
5.8688418865204 तैयार
4.2948560714722 क्वेरी
4.9533629417419 क्वेरी
5.9051351547241 तैयार
४.३३२१०२०६०३१८ क्वेरी
5.9672858715057 तैयार
5.0667371749878 क्वेरी
3.8260300159454 क्वेरी
4.0791549682617 क्वेरी
4.3775160312653 क्वेरी
3.6910600662231 क्वेरी
5.2708210945129 तैयार
6.2671611309052 तैयार
7.3791449069977 तैयार
(7) औसत तैयार: 6.0673267160143
(8) क्वेरी औसत: 4.3276024162769
मैं यह देखने के लिए उत्सुक हूं कि यह परीक्षण अन्य वातावरण में कैसे तुलना करता है, जैसे MySQL।