PHP से MySQL से जुड़ना बेहद धीमा है


19

मैंने अभी-अभी XAMPP की नई स्थापना की है। जब पहली बार PHPMyAdmin खोलने पर मैंने देखा कि यह बहुत धीमा था। यह समझ में नहीं आया कि लोकलहोस्ट पर इसे हर पेज को खोलने में लगभग 5 सेकंड लगने चाहिए। मैंने PHPMyAdmin को दोष देने के लिए एक छोटा परीक्षण मामला बनाया:

$con = new PDO("mysql:host=localhost;dbname=mysql", "root", "");
$statement = $con->query('SELECT host,user,password FROM user;');
$users = $statement->fetchAll(PDO::FETCH_ASSOC);

उपरोक्त स्क्रिप्ट को चलने में लगभग 3 सेकंड लगते हैं (हालाँकि मैंने इसे पहली बार चलाने के लिए 8 सेकंड के करीब लिया था।)

फिर यह जांचने के लिए कि क्या यह पीडीओ की गलती थी, मैंने mysql_connectइसके बजाय प्रयोग करने की कोशिश की :

$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');

खत्म करने के लिए लंबे समय के रूप में लेता है।

मैंने सोचा था कि यह पहली बार में PHP की गलती थी, लेकिन PHP कोड और स्थिर फ़ाइलों को स्नैपर की तुलना में परोसा जाता है क्योंकि मैं ताज़ा कर सकता हूं। मैंने इस छोटी स्क्रिप्ट को चलाकर PHP का परीक्षण किया:

header("Content-Type: text/plain");

for($i = 0; $i < 5000; $i++)
{
    echo sha1(rand()) . "\n";
}

5000 sha1गणनाएं और पेज अभी भी प्रदर्शित किया गया है कि मैं अपनी खिड़की को ताज़ा कर सकता हूं।

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

इस मुद्दे पर PHP का MySQL से कनेक्शन होना चाहिए - यही कारण है कि जहाँ तक मैं तर्क करने में सक्षम हूँ। मुझे PHP के धीमा होने या MySQL धीमा होने के बारे में बहुत सारे सामान मिल सकते हैं, लेकिन PHP + MySQL के बारे में कुछ भी धीमा नहीं है।

किसी को भी धन्यवाद, जो मुझे इसे हल करने में मदद कर सकता है!


मैं win32 ( डाउनलोड लिंक )
PHP संस्करण: 5.4.4
MySQL संस्करण: 14.14 के लिए XAMPP 1.8.0 का उपयोग कर रहा हूं


संपादित करें: समय के बाद, यह पता चलता है कि यह कनेक्ट फ़ंक्शन है जो इतना लंबा समय ले रहा है:

$time = microtime(true);

$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);

$con_time = microtime(true);

$result = mysql_query('SELECT host,user,password FROM user;');

$sel_time = microtime(true);

printf("Connect time: %f\nQuery time: %f\n",
       $con_time-$time,
       $sel_time-$con_time);

आउटपुट:

कनेक्ट समय: 1.006148
क्वेरी समय: 0.000247

डेटाबेस से जुड़ने के लिए PHP का अधिक समय खर्च करने का क्या कारण हो सकता है? CLI क्लाइंट, HeidiSQL और MySQL कार्यक्षेत्र तुरंत कनेक्ट करते हैं


php -m आउटपुट कृपया
thinice

जवाबों:


17

क्या यह हो सकता है कि आपका mysql जब भी कनेक्ट हो, रेव-डीएनएस क्वेरी चलाने की कोशिश करे? my.cnf, अनुभाग mysqld में जोड़ने का प्रयास करें: स्किप-नाम-संकल्प


विचित्र रूप से पर्याप्त PHPMyAdmin और MySQL CLI क्लाइंट अब मुझे "होस्ट '127.0.0.1' इस MySQL सर्वर से कनेक्ट करने की अनुमति नहीं है"। किसी कारण के लिए PHP स्क्रिप्ट अभी भी काम करती है, लेकिन पहले की तरह ही धीमी है
हब्रो

mysql को प्रबंधित करने के लिए 'वसा अनुप्रयोग' हैं - जैसे mysql कार्यक्षेत्र - धीमे?
पीक्यूडी

MySQL वर्कबेंच से समान क्वेरी चलाना CLI क्लाइंट की तरह ही तेज़ है, और इसलिए HeidiSQL
Hubro

php में कुछ समय जोड़ें और जांचें कि क्या यह क्वेरी को कनेक्ट या चला रहा है जिसमें बहुत समय लगता है।
pQd

उस टिप्पणी के लिए धन्यवाद, मैंने अपना प्रश्न अपडेट किया। कनेक्शन और क्वेरी दोनों सुपर फास्ट है
हब्रो

30

यह यहाँ मेरे जवाब से लगभग शब्दशः लिया गया है , लेकिन मुझे पता है कि हम SO पर लिंक-ओनली उत्तरों पर ही भौंकते हैं, इसलिए मुझे लगता है कि आप लोग भी ऐसा करते हैं :-)

यदि आपको यह समस्या हो रही है और विंडोज 7 से पहले विंडोज के एक संस्करण का उपयोग कर रहे हैं, तो यह शायद आपकी समस्या का जवाब नहीं है।

ये क्यों हो रहा है?

इस समस्या का कारण IPv4 बनाम IPv6 है।

जब आप IP पते के बजाय एक होस्ट नाम का उपयोग करते हैं, तो MySQL क्लाइंट पहले AAAAनाम के लिए (IPv6) होस्ट लुकअप चलाता है , और यदि IPv6 पते के लिए सफलतापूर्वक नाम हल करता है, तो पहले इस पते की कोशिश करता है। यदि या तो चरण विफल होता है (नाम समाधान या कनेक्शन) तो यह IPv4 पर वापस आ जाएगा, एक Aलुकअप चलाने और इसके बजाय इस होस्ट को आज़माने के लिए।

व्यवहार में इसका मतलब यह है कि यदि IPv6 localhostलुकअप सफल है, लेकिन MySQL IPv6 लूपबैक के लिए बाध्य नहीं है, तो आपको IPv4 फ़ॉलबैक होने से पहले एक कनेक्शन टाइमआउट चक्र की प्रतीक्षा करनी होगी और कनेक्शन सफल हो जाएगा।

यह विंडोज 7 से पहले का मुद्दा नहीं था, क्योंकि localhostमेजबानों की फाइल के माध्यम से रिजॉल्यूशन किया गया था, और यह केवल प्री-कॉन्फिगर हो गया 127.0.0.1- यह IPv6 समकक्ष के साथ नहीं आया ::1

विंडोज 7 के बाद से, हालांकि, localhostरिज़ॉल्यूशन को डीएनएस रिज़ॉल्वर में बनाया गया है, यहां उल्लिखित कारणों से । इसका अर्थ है कि IPv6 लुकअप अब सफल हो जाएगा - लेकिन MySQL उस IPv6 पते से बँधा नहीं है, इसलिए कनेक्शन विफल हो जाएगा, और आपको इस प्रश्न में उल्लिखित विलंब दिखाई देगा।

यह अच्छा है। बस मुझे बताएं कि इसे पहले से ही कैसे ठीक किया जाए!

आपके पास कुछ विकल्प हैं। इंटरनेट के चारों ओर देखते हुए, सामान्य "समाधान" के नाम के बजाय स्पष्ट रूप से आईपी पते का उपयोग करना प्रतीत होता है, लेकिन ऐसा न करने के कुछ कारण हैं, दोनों पोर्टेबिलिटी संबंधित हैं, दोनों यकीनन महत्वपूर्ण नहीं हैं:

  • यदि आप अपनी स्क्रिप्ट को किसी अन्य मशीन पर ले जाते हैं जो केवल IPv6 का समर्थन करती है, तो आपकी स्क्रिप्ट अब काम नहीं करेगी।

  • यदि आप अपनी स्क्रिप्ट को * nix- आधारित होस्टिंग वातावरण में स्थानांतरित करते हैं, तो जादुई स्ट्रिंग localhostका अर्थ होगा कि MySQL क्लाइंट एक यूनिक्स सॉकेट का उपयोग करना पसंद करेगा यदि कोई कॉन्फ़िगर किया गया है, तो यह आईपी लूपबैक आधारित कनेक्टिविटी की तुलना में अधिक कुशल है।

वे हालांकि बहुत महत्वपूर्ण ध्वनि?

वे नहीं कर रहे हैं आपको अपना एप्लिकेशन डिज़ाइन करना चाहिए ताकि कॉन्फ़िगरेशन फ़ाइल में इस तरह की चीज़ परिभाषित हो। यदि आप अपनी स्क्रिप्ट को किसी अन्य वातावरण में ले जाते हैं, तो संभावना है कि अन्य चीजों को भी कॉन्फ़िगर करने की आवश्यकता होगी।

सारांश में, आईपी पते का उपयोग करना सबसे अच्छा समाधान नहीं है, लेकिन यह सबसे अधिक स्वीकार्य है।

तो सबसे अच्छा उपाय क्या है?

सबसे अच्छा तरीका यह होगा कि MySQL सर्वर द्वारा उपयोग किए जाने वाले बाइंड एड्रेस को बदल दिया जाए। हालांकि, यह उतना आसान नहीं है जितना कोई पसंद कर सकता है। अपाचे, नग्नेक्स और लगभग हर दूसरे साने नेटवर्क सर्विस एप्लिकेशन के विपरीत, MySQL केवल एक बाइंड पते का समर्थन करता है, इसलिए यह केवल एक और जोड़ने का मामला नहीं है। सौभाग्य से, ऑपरेटिंग सिस्टम यहां जादू का समर्थन करते हैं, इसलिए हम MySQL को IPv4 और IPv6 दोनों का एक साथ उपयोग करने में सक्षम कर सकते हैं।

आपको MySQL 5.5.3 या बाद का संस्करण चलाने की आवश्यकता है, और आपको --bind-address=कमांड लाइन तर्क के साथ MySQL शुरू करने की आवश्यकता है । आपके पास 4 विकल्प डॉक्स हैं , जो आप करना चाहते हैं उसके आधार पर:

  • जिस से आप शायद परिचित हैं, और जिसको आप उपयोग करने की सबसे अधिक संभावना है (प्रभावी रूप से) 0.0.0.0। यह मशीन पर उपलब्ध सभी IPv4 पतों को बांधता है। यह वास्तव में शायद सबसे अच्छी बात नहीं है, भले ही आप आईपीवी 6 के बारे में परवाह न करें, क्योंकि यह समान सुरक्षा जोखिमों से ग्रस्त है ::

  • एक स्पष्ट IPv4 या IPv6 पता (उदाहरण के लिए 127.0.0.1या ::1लूपबैक के लिए)। यह सर्वर को उस पते पर बांधता है और केवल उस पते को।

  • जादू की तार ::। यह MySQL को IPv4 और IPv6 मोड में मशीन, लूपबैक और फिजिकल इंटरफेस एड्रेस दोनों पर हर पते पर बाँध देगा। यह संभावित रूप से एक सुरक्षा जोखिम है, केवल तभी करें जब आपको दूरस्थ होस्ट से कनेक्शन स्वीकार करने के लिए MySQL की आवश्यकता हो।

  • IPv4- मैप्ड IPv6 पते का उपयोग करें । यह 4 -> 6 संक्रमण के दौरान पीछे की संगतता के लिए IPv6 में बनाया गया एक विशेष तंत्र है, और यह आपको एक विशिष्ट IPv4 पते से बांधने की अनुमति देता है और यह IPv6 के बराबर है। यह आपके लिए "दोहरे लूपबैक" पते के अलावा किसी अन्य चीज़ के लिए उपयोगी होने की संभावना नहीं है ::ffff:127.0.0.1। यह ज्यादातर लोगों के लिए सबसे अच्छा समाधान है, केवल लूपबैक के लिए बाध्य है, लेकिन आईपीवी 4 और आईपीवी 6 कनेक्शन दोनों की अनुमति देता है।

क्या मुझे होस्ट फ़ाइल को संशोधित करने की आवश्यकता है?

सं । होस्ट फ़ाइल को संशोधित न करें। DNS रिज़ॉल्वर जानता है कि इसके साथ क्या करना है localhost, इसे फिर से परिभाषित करने का कोई प्रभाव नहीं होगा, और सबसे खराब रूप से रिज़ॉल्वर से नरक को भ्रमित करेगा।

किस बारे में --skip-name-resolve?

यह संबंधित, लेकिन थोड़ा अलग कारण से भी समस्या को ठीक कर सकता है।

इस कॉन्फ़िगरेशन विकल्प के बिना, MySQL PTRDNS क्वेरी के माध्यम से होस्टनाम के लिए सभी क्लाइंट कनेक्शन आईपी पते को हल करने का प्रयास करेगा । यदि आपका MySQL सर्वर पहले से ही IPv6 का उपयोग करने में सक्षम है, लेकिन कनेक्शन अभी भी लंबा समय ले रहे हैं, तो यह हो सकता है क्योंकि रिवर्स DNS ( PTR) रिकॉर्ड सही तरीके से कॉन्फ़िगर नहीं किया गया है।

नाम रिज़ॉल्यूशन को अक्षम करने से यह समस्या ठीक हो जाएगी, लेकिन इसमें अन्य व्यवधान हैं, विशेष रूप से यह कि Hostकंडीशन में DNS नाम का उपयोग करने के लिए कॉन्फ़िगर की गई कोई भी एक्सेस अनुमतियाँ अब विफल हो जाएंगी।

यदि आप ऐसा करने जा रहे हैं, तो आपको नामों के बजाय आईपी पते का उपयोग करने के लिए अपने सभी अनुदानों को कॉन्फ़िगर करने की आवश्यकता होगी।


2
आखिरकार! शुक्रिया शुक्रिया! अंत में मुझे सभी कारणों, संभावित समाधानों और उनके प्रतिवादों का उचित, पूर्ण और स्पष्ट विवरण मिला। आपको इसके बारे में एक किताब लिखनी चाहिए!
तोबिया.जानारेला

4
जब तक मैंने बाइंड-एड्रेस को नहीं बदला, मुझे लोकलहोस्ट पर MySQL से कनेक्ट होने में 1 सेकंड की देरी हो रही थी ::1। दुर्भाग्य से ::ffff:127.0.0.1मुझे 1 सेकंड की देरी देना जारी रखा (उपयोग करने skip-name-resolveया नहीं करने की परवाह किए बिना ), किसी भी विचार क्यों? (विंडोज 8.1 पर)
साइमन ईस्ट

1
@ साइमन बिना देखे सुराग नहीं है, लेकिन डीबग करने के लिए पहला कदम आईपीवी 6 लूपबैक और आईपीवी 4 लूपबैक दोनों से जुड़ने की कोशिश करना होगा, ताकि स्पष्ट पते का उपयोग करके सीधे यह पता लगाया जा सके कि माईसेल वास्तव में दोनों ढेर पर सुन रहा है और कनेक्ट करने योग्य है, और वहां से डिबगिंग। ।
डेवग्रैंड फेन

1
yea, :: ffff: 127.0.0.1 doesn't काम ...
रहेल हसन

अगर मैं इसे :: 1 के साथ बांधता हूं, Sqlyog doesn't काम करता है ... क्या करना है ??
रहेल हसन

13

आमतौर पर जब IPv6 सर्वर कनेक्शन में MySQL का उपयोग करने में सक्षम होता है तो localhostबेहद धीमी गति से होता है।

127.0.0.1समस्या को हल करने के लिए स्क्रिप्ट में mysql सर्वर एड्रेस को बदलना ।


+1 यह मेरे लिए सही उत्तर था। मुझे लगता है कि विंडोज 8 में वे localhostइस कारण से डीएनएस रिज़ॉल्वर के रिज़ॉल्यूशन को स्थानांतरित कर देते हैं कि @DaveRandom से जुड़ा है: serverfault.com/questions/4689/…
wwarren

इसने मेरे लिए काम किया: D
FosAvance

यह अन्य सर्वरों की तुलना में हो सकता है localhost। मुझे प्रपत्र पर सर्वर पते के लिए समान विलंब समस्या थी xx.xxxx.xxxxx.xxxxx.com। एक बार जब मैंने सर्वर का नाम उसके आईपी पते में बदल दिया, तो समस्या दूर हो गई।
ग्रुबर

1
mysql_connect("localhost", "root", "");

खैर, यह काफी स्पष्ट है कि इसका कारण क्या है। PHP वास्तव में कुछ चीजों में अच्छी है, लेकिन सीधे 'लोकलहोस्ट' का '127.0.0.1' में अनुवाद नहीं कर रही है। आपको यह कोशिश करनी चाहिए कि, यह वास्तव में आपके समग्र वेबसाइट पेज को लोड करने का समय कम कर देगा, क्योंकि यह PHP को आपके HOSTS फ़ाइल की जाँच करने से पीछे रखता है और यह 'लोकलहोस्ट' के पीछे असली आईपी एड्रेस प्राप्त करने के लिए क्या नहीं कर रहा है।


मैं यह पता नहीं लगा सकता कि आप समस्या के बारे में क्या सुझाव देना चाह रहे हैं।
कैस्परल्ड

@kasperd DNS 'लोकलहोस्ट' का समाधान
Xesau

'17 से नोट करें - mysql_ * फ़ंक्शन अब हटाए गए हैं और php7 में हटा दिए गए हैं
treyBake

1

अपने होस्ट फ़ाइल में इस लाइन को जोड़ने से मेरे लिए समस्या हल हो गई

127.0.0.1 localhost

इस धागे में विस्तृत उत्तर पाया जा सकता है: /programming/13584360/php-with-mysql-is-slow


0

आप अपने db कनेक्शन वैरिएबल (जो पोर्टेबिलिटी के लिए आपकी स्क्रिप्ट से अलग फाइल में उम्मीद के मुताबिक है) में एक छोटा सा समायोजन करके क्वेरी स्लोडाउन को भी खत्म कर सकते हैं। "लोकलहोस्ट" के बजाय होस्ट वैल्यू को "127.0.0.1" में बदलें। यह लोकलहोस्ट के लिए लंबी DNS लुकअप को बायपास करता है।

उम्मीद है की यह मदद करेगा!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.