2010-04-01 7 views
12

मैंने एक अफवाह सुनाई कि बाईरी डेटा (फाइलें और इस तरह) को MySQL में डालने पर, आपको bin2hex() फ़ंक्शन का उपयोग करना चाहिए और इसे बाइनरी स्ट्रिंग पर mysql_real_escape_string का उपयोग करने के बजाय हेक्स-कोडेड मान के रूप में भेजना चाहिए।PHP से MySQL में बाइनरी डेटा डालने पर bin2hex का उपयोग क्यों करें?

// That you should do 
$hex = bin2hex($raw_bin); 
$sql = "INSERT INTO `table`(`file`) VALUES (X'{$hex}')"; 

// Rather than 
$bin = mysql_real_escape_string($raw_bin); 
$sql = "INSERT INTO `table`(`file`) VALUES ('{$bin}')"; 

यह प्रदर्शन कारणों से माना जाता है। MySQL बड़े स्ट्रिंग्स को कैसे प्रबंधित करता है इसके साथ कुछ करने के लिए। यह हेक्स-कोडित मानों को कैसे नियंत्रित करता है

हालांकि, मुझे इसकी पुष्टि करने में कठिनाई हो रही है। मेरे सभी परीक्षण सटीक oposite इंगित करते हैं; कि bin2hex विधि ~ 85% धीमी है और ~ 24% अधिक स्मृति का उपयोग करती है।
(मैं PHP 5.3, MySQL 5.1 पर इस परीक्षण कर रहा हूँ, Win7 x64 -। एक farily सरल डालने पाश का उपयोग करना)

उदाहरण के लिए, इस ग्राफ mysqld प्रक्रिया के निजी स्मृति उपयोग परीक्षण करते हुए पता चलता कोड चल रहा था:

Private Bytes used by the mysqld process http://atli.advefir.com/images/priv_mem_cropped.gif

किसी को भी किसी भी explainations या reasources कि इस स्पष्ट होता है?

धन्यवाद।

+0

वहाँ एक अंतर प्रदर्शन का उपयोग करने पर '" में \ 'तालिका \ INSERT' (\ 'फ़ाइल \') मान (एक्स {हो सकता है $ हेक्स}) ";" (हेक्स वैल्यू को छोड़ने से उद्धरण हटाएं)? (+1 बीटीडब्ल्यू) – Jacco

+0

@Jacco सुझाव के लिए धन्यवाद। मैंने कुछ परीक्षण किए और दो विधियां लगभग समान रूप से प्रदर्शन करने लगती हैं। 'एक्स' ... '' विधि मेमोरी और सीपीयू उपयोग दोनों में मामूली बढ़त प्रतीत होती है। - यदि आप रुचि रखते हैं तो मैंने परिणामों को एक साथ संपादित किया और उन्हें अपलोड किया: http://atli.advefir.com/images/myisam_joined.png, http://atli.advefir.com/images/innodb_joined.png – Atli

+0

दिलचस्प, मैं वास्तव में 'क्यों' व्याख्या करने के लिए एक डीबीए पसंद करूंगा। – Jacco

उत्तर

9

यह मेरे लिए एक शहरी कथा की तरह लगता है। , - (>'61''a') ताकि आप पूछताछ स्क्रिप्ट की एक महत्वपूर्ण स्मृति वृद्धि नोटिस देना चाहिए -

bin2hex() उत्पादन में दो बाइट्स के लिए इनपुट में प्रत्येक बाइट नक्शे यह कम से कम के रूप में ज्यादा स्मृति अधिक का उपयोग करना चाहिए बाइनरी डेटा डालने के बाइट लंबाई के रूप में। NULL, \r, \n, \, , और 'नियंत्रण-जेड:

इसके अलावा, यह संकेत मिलता है एक लंबी स्ट्रिंग पर bin2hex() चल लेता है कि mysql_real_escape string(), जो चलाने की तुलना में ज्यादा अब - - के रूप में MySQL's documentation में विस्तार से बताया सिर्फ 6 अक्षर निकल जाता है '।

वह PHP भाग के लिए था, अब MySQL के लिए: सर्वर को डेटा को सही तरीके से स्टोर करने के लिए रिवर्स ऑपरेशन करने की आवश्यकता है।कार्यों में से किसी एक को उलट करने से लगभग मूल ऑपरेशन होता है - mysql_real_escape_string() के रिवर्स फ़ंक्शन से बचने वाले मूल्यों (\\) को अनचाहे वाले लोगों (\) के साथ प्रतिस्थापित करने की आवश्यकता होती है, जबकि bin2hex() के विपरीत को प्रत्येक बाइट ट्यूपल को प्रतिस्थापित करने की आवश्यकता होगी एक नया बाइट के साथ।

के बाद से बाइनरी डेटा पर mysql_real_escape_string() बुला सुरक्षित है (MySQL के और PHP's documentation या यहाँ तक कि के अनुसार जब सिर्फ इतना है कि आपरेशन में ऊपर सूचीबद्ध के किसी अन्य रूपांतरण नहीं करता है पर विचार), यह बिल्कुल कोई मतलब नहीं होगा इस तरह के एक प्रदर्शन करने के लिए महंगा ऑपरेशन।

+0

यह समझ में आता है। अकेले PHP में क्वेरी स्ट्रिंग को स्टोर करने के लिए आवश्यक अतिरिक्त मेमोरी 'bin2hex' फ़ंक्शन से बचने के लिए पर्याप्त कारण प्रतीत होती है, और मेरे स्वयं के परीक्षण इंगित करते हैं कि MySQL भी पीड़ित है। और फिर रूपांतरणों की अतिरिक्त सीपीयू लागत है। - यह वास्तव में एक शहरी किंवदंती की तरह अधिक से अधिक लग रहा है। फिर भी, मुझे आश्चर्य है कि यह क्या शुरू हुआ; लोग क्यों सोचते हैं कि यह एक अच्छा विचार है। – Atli

+0

मुझे लगता है कि कुछ लोगों ने सोचा था कि '..._ escape_string' नामक फ़ंक्शन के साथ बाइनरी डेटा को एन्कोड करना या मानव-पठनीय SQL कथन के भीतर बाइनरी डेटा भेजने के लिए मूर्खतापूर्ण हो सकता है, लेकिन वास्तव में इसमें कुछ भी गलत नहीं है (हालांकि वहां कुछ भी गलत हो सकता है फ़ंक्शन के लिए उपनाम रहा है - जैसे 'mysql_escape_data() 'या इसी तरह) – soulmerge

+0

अच्छे अंक। मैं देख सकता हूं कि लोग इस तरह से कैसे देख सकते हैं, खासकर जो दृढ़ता से टाइप की गई भाषाओं से आते हैं। - मैंने वास्तव में उन सभी को कभी भी अलग नहीं माना, हालांकि। मेरा मतलब है, पीएचपी स्ट्रिंग मूल रूप से बस बाइटरी डेटा की तरह बाइट एरे हैं। (PHP 6 तक, कम से कम।) – Atli

4

एक हेक्स स्ट्रिंग संबंधित बाइनरी स्ट्रिंग से काफी लंबा है। बस स्थानांतरण समय और PHP और MySQL की स्मृति के अंदर इसे कॉपी करने से चाल चल सकती है।

सभी ईमानदारी में मैं अंतर्निहित कार्यान्वयन पर विशेषज्ञ नहीं हूं, लेकिन एसक्यूएल के अंदर डेटा को पास नहीं करना बेहतर होगा, लेकिन उदाहरण के लिए PDOStatement पैरामीटर बाध्यकारी? शायद यहां कोई और जानकार यह पुष्टि कर सकता है कि क्या वास्तव में किसी भी SQL कथन के बाहर डेटा को द्विआधारी स्ट्रिंग के रूप में भेजा जाएगा, या पीडीओ सिर्फ हुड के नीचे से बचने और क्वेरी स्ट्रिंग मैनिपुलेशन करता है या नहीं।

किसी भी तरह से, आपको वहां एक सुरक्षा (और सादगी) लाभ मिलता है।

+0

उत्तर के लिए धन्यवाद। हालांकि यह मेरा पहला था; कि रूपांतरण प्रक्रिया और स्ट्रिंग की अतिरिक्त लंबाई कम प्रदर्शन का कारण बन जाएगी। और ऐसा प्रतीत होता है कि हम सही हैं। - हालांकि, अब मुझे कई पेज मिले हैं जो 'bin2hex' फ़ंक्शन (या यहां तक ​​कि, अधिक परेशान, बेस 64 फ़ंक्शंस) का उपयोग दिखाते हैं, और मुझे कोई कारण नहीं दिख रहा है। इसका कोई मतलब नहीं है ... - बीटीडब्ल्यू, व्यक्तिगत रूप से मैं तैयार कथन (आमतौर पर, mysqli) का उपयोग करता हूं। यह सवाल व्यावहारिक से अधिक काल्पनिक है :) – Atli

+0

bin2hex/base64 किसी भी चरित्र सेट के मुद्दों से बच जाएगा, अगर तालिका (गलती से) BLOB के बजाय टेक्स्ट फ़ील्ड के साथ बनाई गई थी। लेकिन डेटा आकार में अप-टू-3x की वृद्धि की लागत पर (मानते हुए कि डेटा पूरी तरह से गैर-असीसी है और पूरी तरह से% xx% yy% zz में परिवर्तित हो गया है ...) –

+0

हेक्स और बेस 64 दोनों डेटा भेजने के आकार को बढ़ाते हैं । हेक्स के साथ डेटा बाइनरी के रूप में संग्रहीत किया जाता है। बाद में डेटा बेस 64 एन्कोडेड प्रारूप में संग्रहीत किया जाता है और इस प्रकार 33% बड़ा होता है। (लेकिन यह ओपी के सवाल का जवाब नहीं देता है) – Jacco

5

मैं इसे स्वयं परीक्षण कर रहा हूं, और मैं काफी लगातार परिणाम लेकर आया हूं। (भले ही मेरी परीक्षण एक बालक कच्चे हैं।)

मैं तीन कंप्यूटर

परीक्षण किया है
  1. विंडोज 7 (64), पीएचपी 5.3, MySQL 5.1
  2. उबंटू 9.10 (64) पीएचपी 5.2 , MySQL 5.1
  3. उबंटू 10.04 (x32) पीएचपी 5.3, MySQL 5,1

अब तक सभी तीन प्लेटफार्मों पर परीक्षण संकेत दिया है एक ही सी चीज़ें:

012,351,
  • आईओओडीबी की तुलना में एक बीएलओबी में सम्मिलित करना MyISAM पर 2x से 8x तेज है। अंतर हेक्स-कोडित तारों की तुलना में द्विआधारी तारों पर अधिक प्रतीत होता है।(एक X'...' में bin2hex) एक हेक्स स्ट्रिंग कोडित का उपयोग करना
  • (नीचे डेटा देखें), अधिक मेमोरी का उपयोग करता औसतन एक भाग निकले बाइनरी स्ट्रिंग (mysql_real_escape_string कच्चे डेटा पर) का उपयोग करने से। - यह MyISAM और InnoDB दोनों के लिए सच लगता है।
  • माईसाम पर द्विआधारी स्ट्रिंग तेज है, लेकिन हेक्स-कोडित डेटा InnoDB पर तेज़ है।

परीक्षण मूल रूप से सिर्फ एक सरल पाश है कि बच गए या हेक्स कोडित कच्चे डेटा (2.4 MiB छवि स्क्रिप्ट के शीर्ष पर एक बार पुनः प्राप्त), निर्माण क्वेरी स्ट्रिंग था, और मार डाला यह mysql_query या mysqli::query फ़ंक्शंस के माध्यम से। - मैंने दोनों एक्सटेंशन के साथ परीक्षण किया। कोई फर्क नहीं पड़ता।

मैंने परिणाम स्प्रेडशीट में उबंटू 10.04 (# 3) से ऊपर रखे। उबंटू 9.10 (# 2) मशीन से परिणाम बहुत ज्यादा एक ही थे, तो मैं उन्हें सेट अप परेशान नहीं किया: (! अंत में एक बहाना गूगल डॉक्स बात ठीक से परीक्षण करने के लिए xD)

ये ग्राफ Win7 (# 1) मशीन पर mysqld प्रक्रिया द्वारा निजी मेमोरी उपयोग दिखाते हैं।

0

उदाहरण के लिए यदि आप समान समस्या का सामना यहाँ वर्णित के रूप में: http://www.php.net/manual/en/function.mysql-real-escape-string.php#82015

उदा भले ही mysql_real_escape_string "बाइनरी-सुरक्षित" प्रतीत होता है, आप इसका उपयोग नहीं कर सकते (उदाहरण के रूप में) igbinary_serialize के साथ संयोजन में - unserializing बस असफल हो जाएगा।

उस स्थिति में आपको mysql में डेटा डालने से पहले bin2hex की आवश्यकता है।

इसके अलावा, आम तौर पर आपको अधिक बार डेटा mysql से डालने :) से पढ़

संबंधित मुद्दे