2012-07-06 9 views
5

मैं जानना चाहता हूं कि निम्न स्थितियों में से कौन सा उदाहरण मेरी स्थिति में रिकॉर्डसेट ऑब्जेक्ट को बंद करने के लिए सबसे अच्छा है?क्लासिक एएसपी - रिकॉर्डसेट को बंद करने के लिए

1)

यह एक पाश अंदर वस्तु बंद कर देता है, लेकिन एक नई वस्तु को खोलता है, जब यह अगले ले जाता है। यदि 1000 रिकॉर्ड थे, तो यह एक ऑब्जेक्ट 1000 बार खुलता है और इसे 1000 बार बंद करता है। यह वही है मैं सामान्य रूप से करना होगा है:

SQL = " ... " 
Set rs1 = conn.Execute(SQL) 
While NOT rs1.EOF 

    SQL = " ... " 
    Set rs2 = conn.Execute(SQL) 
    If NOT rs2.EOF Then 
     Response.Write (...) 
    End If 
    rs2.Close : set rs2 = Nothing 

rs1.MoveNext 
Wend 
rs1.Close : Set rs1 = Nothing 

2)

यह उदाहरण है कि मैं क्या बारे में जानना चाहते है। लूप समाप्त होने के बाद ऑब्जेक्ट क्लोजर (rs2.close) को सहेजता है, लाभ प्राप्त करता है या प्रदर्शन को कम करता है? अगर 1000 के रिकॉर्ड थे, यह 1000 वस्तुओं खोलता था लेकिन केवल एक बार यह बंद कर देता है:

SQL = " ... " 
Set rs1 = conn.Execute(SQL) 
While NOT rs1.EOF 

    SQL = " ... " 
    Set rs2 = conn.Execute(SQL) 
    If NOT rs2.EOF Then 
     Response.Write (...) 
    End If 

rs1.MoveNext 
Wend 
rs1.Close : Set rs1 = Nothing 
rs2.Close : set rs2 = Nothing 

मुझे आशा है कि मैं अपने आप को काफी अच्छी तरह से समझाया है और यह भी बेवकूफ नहीं है।

अद्यतन

जो लोग सोचते हैं मेरी क्वेरी एन 1 मुद्दों (2 क्वेरी) से बचने के लिए संशोधित किया जा सकता करने के लिए

, यहाँ यह है:

यह एक ऑनलाइन फोटो लाइब्रेरी के लिए है। मेरे पास दो टेबल हैं; "फोटोशर्च" और "फोटो"। पहला, "फोटोशर्च" में केवल कुछ कॉलम हैं और फ़ोटो के लिए सभी खोजे जाने योग्य डेटा हैं, जैसे "फोटोआईडी", "हेडलाइन", "कैप्शन", "लोग", "डेट कैप्चर" और "कीवर्ड"। इसमें एक बहु-स्तंभ पूर्ण-पाठ अनुक्रमणिका है (शीर्षक, कैप्शन, लोग, कीवर्ड)। दूसरी तालिका, "फोटो" में, सभी फोटो डेटा शामिल हैं; ऊंचाई, चौड़ाई, कॉपीराइट, कैप्शन, आईडी, तिथियां और बहुत कुछ। दोनों में 500 के + पंक्तियां हैं और शीर्षक और कैप्शन फ़ील्ड कभी-कभी 2000+ अक्षर लौटाते हैं।

यह लगभग है कि क्वेरी अब कैसे दिखती है: (ध्यान दें: मैं पूर्ण टेक्स्ट खोज के साथ जुड़ने का उपयोग नहीं कर सकता, इसलिए कीवर्ड को एक कॉलम में संग्रहीत किया जा रहा है - 'डी-सामान्यीकृत' तालिका में। इसके अलावा, इस तरह का छद्म मेरे ऐप कोड के रूप में कोड कहीं और है - लेकिन यह करीब है)

SQL = "SELECT photoID FROM photoSearch 
WHERE MATCH (headline, caption, people, keywords) 
AGAINST ('"&booleanSearchStr&"' IN BOOLEAN MODE) 
AND dateCaptured BETWEEN '"&fromDate&"' AND '"&toDate&"' LIMIT 0,50;" 
Set rs1 = conn.Execute(SQL) 
While NOT rs1.EOF 

    SQL = "SELECT photoID, setID, eventID, locationID, headline, caption, instructions, dateCaptured, dateUploaded, status, uploaderID, thumbH, thumbW, previewH, previewW, + more FROM photos LEFT JOIN events AS e USING (eventID) LEFT JOIN location AS l USING (locationID) WHERE photoID = "&rs1.Fields("photoID")&";" 
    Set rs2 = conn.Execute(SQL) 
    If NOT rs2.EOF Then 
     Response.Write (.. photo data ..) 
    End If 
    rs2.Close 

rs1.MoveNext 
Wend 
rs1.Close 

है, जांच की अपनी ही मेज, "PhotoSearch" पर पूर्ण-पाठ सूचकांक होने, बड़ी मेज के बजाय, "फ़ोटो", सुधार करने के लिए लग रहा था कुछ हद तक गति। मैंने "फोटोशर्च" तालिका नहीं जोड़ा, यह पहले से ही था - यह मेरा ऐप नहीं है। यदि मैं दूसरी क्वेरी खोने के लिए दो तालिकाओं में शामिल होने का प्रयास करता हूं, तो मैं अपने इंडेक्सिंग को एक साथ खो देता हूं, जिसके परिणामस्वरूप बहुत लंबा समय होता है - इसलिए मैं पूर्ण-पाठ के साथ जुड़ने का उपयोग नहीं कर सकता। यह बस सबसे तेज विधि प्रतीत होता था। अगर यह पूर्ण पाठ और समस्याओं में शामिल होने के लिए नहीं था, तो मैं पहले से ही इन दोनों प्रश्नों को जोड़ता।

उत्तर

4

यह बात है। सबसे पहले, अपनी फोटो आईडी प्राप्त करें और MySQL सोचें कि एक वास्तविक तालिका है जो केवल फोटो आईडी को पकड़ती है, और फिर अपना वास्तविक विवरण बनाते हैं, किसी भी अतिरिक्त रिकॉर्डसेट कनेक्शन की आवश्यकता नहीं है ...

और इससे शुरू करना न भूलें ऐसा करने के लिए अंत। यहाँ स्पष्टीकरण के साथ नमूना कोड है:

चरण 1 तस्वीर आईडी लुकअप तालिका और यह नाम बनाएँ: यह हमारी PHOTOID लुक-अप तालिका तो "PhotoIds"

SELECT photoID FROM photoSearch 
WHERE MATCH (headline, caption, people, keywords) 
AGAINST ('"&booleanSearchStr&"' IN BOOLEAN MODE) 
AND dateCaptured BETWEEN '"&fromDate&"' AND '"&toDate&"' LIMIT 0,50) AS PhotoIds 

चरण 2 अब के रूप में यह नाम होगा हमारे पास फोटो आईडी हैं, इसलिए इससे जानकारी प्राप्त करें। हम उपरोक्त कथन को पहले कहां से पहले बताएंगे जैसा कि हम असली टेबल के साथ करते हैं। ध्यान दें कि हमारी "नकली" तालिका parantheses के बीच होना चाहिए।

SQL = "SELECT p.photoID, p.setID, p.eventID, p.locationID, p.headline, p.caption, + more FROM 
    photos AS p, 
    events AS e USING (p.eventID), 
    location AS l USING (p.locationID), 
    (SELECT photoID FROM photoSearch WHERE MATCH (headline, caption, people, keywords) 
     AGAINST ('"&booleanSearchStr&"' IN BOOLEAN MODE) AND dateCaptured BETWEEN 
     '"&fromDate&"' AND '"&toDate&"' LIMIT 0,50) AS PhotoIds 
    WHERE p.photoID=PhotoIds.photoID;" 

नोट: मैं सिर्फ इन कोड लिखना यहाँ और कभी नहीं परीक्षण किया गया। कुछ वर्तनी त्रुटियां या smt हो सकती है। यदि आपको परेशानी है तो कृपया मुझे बताएं।

अब, निष्पादित प्रश्नों को बंद करने की कोई ज़रूरत नहीं अपनी प्राथमिक सवाल हो रही

खासकर यदि आप निष्पादित विधि का उपयोग कर रहे हैं। एक्जिक्यूट विधि निष्पादन के बाद खुद को बंद कर देता है जब तक कि यह किसी भी रिकॉर्डसेट डेटा को वापस नहीं लौटाता (जैसे कि पहले स्थान पर निष्पादित कमांड का उद्देश्य): "INSERT", "DELETE", "अद्यतन"। यदि आपने एक रिकॉर्डसेट ऑब्जेक्ट नहीं खोला है, तो कुछ खोले जाने का प्रयास क्यों न करें? इसके बजाय आप का उपयोग कर सकते हैं = कुछ भी ऑब्जेक्ट को अपरिवर्तित करने के लिए सेट करें और कचरा संग्रह को कुछ सिस्टम संसाधनों को मुक्त करने के लिए भेजें (और यह कि MySQL स्वयं से कुछ भी नहीं करना है)। यदि आप "SELECT" क्वेरी का उपयोग कर रहे हैं, (वे प्रश्न जो कुछ डेटा लौटाएंगे) आपको एक रिकॉर्डसेट ऑब्जेक्ट (ADODB.Recordset) खोलना होगा और यदि आपने इसे खोला है, तो इसे अपनी नौकरी खत्म होने के तुरंत बाद इसे बंद करना होगा।

सबसे महत्वपूर्ण बात यह है कि प्रत्येक पृष्ठ लोड के बाद "mysql सर्वर से मुख्य कनेक्शन" को बंद करना सबसे महत्वपूर्ण बात है। तो आप फ़ाइल को शामिल करने के लिए अपने कनेक्शन को बंद एल्गोरिदम (रिकॉर्डसेट बंद नहीं) रखने और डेटाबेस से कनेक्शन बनाने वाले प्रत्येक पृष्ठ के अंत में डालने पर विचार कर सकते हैं।लंबे समय तक बात कम: आप बंद() उपयोग करें यदि आप ओपन इस्तेमाल किया()

+0

वाह! वह नई क्वेरी समझ में आता है और यह काम करता है। मैं MySQL वर्कबेंच में परीक्षण कर रहा हूं और यह बहुत तेज़ है। यह देखने के लिए कि क्या यह चीजों को गति देता है, मुझे इसे अपने ऐप में जोड़ना होगा। मेरा एक सवाल है; मैं इस प्रश्न में एक इंटर्न जॉइन कहां रखूंगा? इस तरह; बाएं जॉइन (फोटो लोग लोग पीपी इनरर पीपी.पीपलआईडी = पी। पीपलआईडीआईडी ​​पर पीई के रूप में लोगों को शामिल करते हैं) पी.फोटोआईडी = पीपी.फोटोआईडी पर? – TheCarver

+0

@PaparazzoKid आपको MySQL के साथ काम करते समय इनर जॉइन, बाएं जॉइन इत्यादि का उपयोग करने की आवश्यकता नहीं है। आप "," (अल्पविराम ऑपरेटर) और छद्म नामों के साथ कई तालिकाओं में शामिल हो सकते हैं। i.e: ("चुनें t1.name, t2.name से बहुत_long_table_name_table1 AS t1, very_long_table_name_table2 AS t2 जहां t1.id = t2.id") – htbasaran

+0

ओह, उसने कार्यों में एक स्पैनर फेंक दिया। मैंने हमेशा MySQL के लिए बाएं, दाएं, जॉइन या इनर जॉइन का उपयोग किया है - मुझे इसके बारे में पढ़ने की आवश्यकता होगी। जिस कारण से मैंने LEFT का उपयोग किया था वह सारणी थी जिसे मैं शामिल करना चाहता हूं, हमेशा मिलान करने वाला रिकॉर्ड नहीं होगा। क्या यह आपकी विधि में समान होगा? – TheCarver

3

यदि आप हमें अपना एसक्यूएल स्टेटमेंट दिखाते हैं, तो हम आपको दिखा सकते हैं कि उन्हें एक एकल SQL कथन में कैसे जोड़ना है ताकि आपको केवल एक लूप करना पड़े, अन्यथा, डबल लूपिंग इस तरह सर्वर प्रदर्शन पर एक टोल लेता है। लेकिन इससे पहले कि मैं संग्रहित प्रक्रियाओं सीखा है और शामिल, शायद मैं इसे इस तरह से किया जाएगा है

Set Conn = Server.CreateObject("Adodb.Connection") 
Conn.Open "ConnectionString" 

Set oRS = Server.CreateObject("Adodb.Recordset") 
oRS.Open "SQL STATEMENT", Conn 

Set oRS2 = Server.CreateObject("Adodb.Recordset") 
oRS2.ActiveConnection = Conn 

Do Until oRS.EOF 

    oRS2.Open "SQL STATEMENT" 
    If oRS2.EOF Then ... 
    oRS2.Close 

oRS.Movenext 
Loop 
oRS.Close 
Set oRS = Nothing 
Set oRS2 = Nothing 
Set Conn = Nothing 
+0

100% सहमत है कि क्वेरी (एँ) के डिजाइन की संभावना आंतरिक क्वेरी पूरी तरह से बचने के लिए सुधार किया जा सकता चाहिए। इसे 'चयन एन + 1 समस्या' के रूप में जाना जाता है http://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem। यदि आप रिकॉर्डसेट ऑब्जेक्ट्स का निपटान कैसे करते हैं, यह अनुकूलित करने के बजाय आप उस मुद्दे पर ध्यान केंद्रित करते हैं तो आपको बेहतर परिणाम मिलेंगे। –

+0

मुझे पता है, मुझे इन दिनों याद है .. एक बार जब मैंने एसक्यूएल प्रश्नों को जोड़ना शुरू किया, तो सर्वर का प्रदर्शन 100x की तरह काफी सुधार हुआ। –

+0

मैं वास्तव में मेरी विधि का उपयोग कर बेहतर परिणाम प्राप्त कर रहा हूं। आजमाया और परखा गया। आम तौर पर मैं कोशिश करता हूं और दो प्रश्नों को एक जैसा करता हूं, जैसा कि आप कहते हैं, लेकिन यह मेरी स्थिति में काम नहीं कर रहा है। मेरी तालिका में 500k पंक्तियां हैं और कई, कई कॉलम, कुछ बड़े कॉलम भी हैं (2000+ अक्षर)। जब मेरा पृष्ठ केवल एक प्रश्न का उपयोग कर रहा था, तो वह उस तालिका में लगभग सभी स्तंभों का चयन कर रहा था और फिर प्रति पृष्ठ 50 रिकॉर्ड प्रदर्शित कर रहा था। सवाल हमेशा के लिए लिया! मैं फिर अपनी उपरोक्त विधि में बदल गया, शीर्ष क्वेरी से केवल आईडी का चयन कर रहा हूं और लूप के अंदर दूसरी क्वेरी से भारी डेटा प्राप्त कर रहा हूं। – TheCarver

0

मैं एक टिप्पणी में इस डाल, क्योंकि यह सीधे अपने मूल प्रश्न का उत्तर न कोशिश की, लेकिन यह बहुत लंबा हो गया .. :)

आप दूसरे के अंदर बाहरी क्वेरी को घोंसले में शामिल होने के बजाय उप-क्वेरी का उपयोग करने का प्रयास कर सकते हैं। "... जहां फोटोआईडी (फोटोशर्च से फोटोआईडी का चयन करें ...)"।सुनिश्चित नहीं है कि यह बेहतर परिणाम प्राप्त करेगा, लेकिन यह कोशिश करने लायक हो सकता है। ऐसा कहा जा रहा है कि पूर्ण-पाठ खोज का उपयोग बदलता है कि प्रश्नों को कैसे अनुकूलित किया जाएगा, इसलिए उचित इंडेक्स (होने की आवश्यकता है) को समझने में अधिक काम हो सकता है। आपके मौजूदा प्रदर्शन के आधार पर, यह प्रयास के लायक नहीं हो सकता है।

क्या आप यह सुनिश्चित करने के लिए जानते हैं कि यह मौजूदा कोड/क्वेरी वर्तमान बाधा है? कभी कभी हम समय बातें हमें लगता है कि कि टोंटी जब यह मामला नहीं हो सकता है कर रहे हैं के अनुकूलन खर्च ... :)

एक अतिरिक्त सोचा - आप अनावश्यक प्रश्नों की मात्रा को कम करने के लिए कुछ कैशिंग तर्क पर विचार कर सकते आप हो सकता है - या तो पेज स्तर पर या इस विधि के स्तर पर। किसी भी प्रकार के कैश में डेटा संग्रहीत करने के लिए कुंजी बनाने के लिए खोज पैरामीटर को एकसाथ संयोजित किया जा सकता है। बेशक आपको उचित कैश अमान्यता/समाप्ति तर्क को संभालने की आवश्यकता होगी। मैंने सिस्टम को 100x की गति को बहुत सरल कैशिंग तर्क के साथ देखा है जैसे इस तरह की बाधाओं में जोड़ा गया है।

+0

कैशिंग मजेदार लगता है, उसमें आगे देख सकते हैं। मेरे पास इस विशेष पृष्ठ या क्वेरी पर वास्तव में कोई बोतल गर्दन नहीं है। मैं पूरी तरह से जानना चाहता था कि एक लूप में इस्तेमाल होने पर रिकॉर्डसेट ऑब्जेक्ट को बंद करने का सबसे अच्छा तरीका क्या था। लूप के बाद या लूप में। – TheCarver

+0

ठीक है - आपने पूछा था कि प्रदर्शन के लिए सबसे अच्छा तरीका कौन सा था, इसलिए मुझे लगता है कि लोगों के लिए आपके कोड के प्रदर्शन पहलू पर ध्यान केंद्रित करना स्वाभाविक है, और इस मामले में क्वेरीसेट ऑब्जेक्ट्स के संचालन की तुलना में क्वेरी का बहुत बड़ा प्रभाव पड़ता है। एक सामान्य सिद्धांत के रूप में यदि आपके पास कोई प्रदर्शन समस्या नहीं है तो आपको शायद इसे अनुकूलित करने में समय बिताना नहीं चाहिए ... :) –

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