2012-07-16 19 views
10

वापस करने के लिए SQL का उपयोग करें यह एक "सर्वोत्तम अभ्यास" प्रश्न है। हम इस विषय पर आंतरिक चर्चा कर रहे हैं और व्यापक दर्शकों से इनपुट प्राप्त करना चाहते हैं।एक JSON स्ट्रिंग

मुझे सामान्य डेटा और पंक्तियों के साथ पारंपरिक MS SQL Server तालिका में अपना डेटा स्टोर करने की आवश्यकता है। मुझे कभी-कभी अपने वेब एप्लिकेशन में DataTable वापस करने की आवश्यकता होती है, और दूसरी बार मुझे JSON स्ट्रिंग वापस करने की आवश्यकता होती है।

वर्तमान में, मैं तालिका को मध्यम परत पर वापस कर देता हूं और इसे JSON स्ट्रिंग में पार्स करता हूं। यह अधिकांश भाग के लिए अच्छी तरह से काम करता प्रतीत होता है, लेकिन कभी-कभी बड़े डेटासेट पर कुछ समय लगता है (डेटा को पार्स कर रहा है, टेबल वापस नहीं कर रहा है)।

मैं DataTable या JSON स्ट्रिंग को चुनिंदा रूप से वापस करने के लिए संग्रहीत प्रक्रियाओं को संशोधित करने पर विचार कर रहा हूं। मैं बस एसपी को @isJson bit पैरामीटर जोड़ दूंगा।

उपयोगकर्ता स्ट्रिंग तालिका के बजाय सपा इस तरह एक प्रश्न पर अमल चाहते थे, तो:

DECLARE @result varchar(MAX) 
SELECT @result = COALESCE(@results ',', '') + '{id:"' + colId + '",name:"' + colName + '"}' 
    FROM MyTable 
SELECT @result 

यह निम्नलिखित की तरह कुछ का उत्पादन:

{id:"1342",name:"row1"},{id:"3424",name:"row2"} 
बेशक

, उपयोगकर्ता कर सकते हैं @isJson पैरामीटर को झूठ बोलकर टेबल भी प्राप्त करें।

मैं स्पष्ट होना चाहता हूं कि डेटा संग्रहण प्रभावित नहीं है, न ही मौजूदा दृश्यों और अन्य प्रक्रियाओं में से कोई भी है। यह केवल कुछ संग्रहीत प्रक्रियाओं के परिणामों में बदलाव है।

मेरे प्रश्न हैं:

  1. किसी को भी एक बड़ी आवेदन में यह करने की कोशिश की है? यदि हां, तो परिणाम क्या था?
  2. आपने इस दृष्टिकोण के साथ क्या समस्याएं देखी हैं/क्या आप उम्मीद करेंगे?
  3. क्या इस तरह से संग्रहीत प्रक्रिया को संशोधित करने या मध्य स्तर में स्ट्रिंग को पार्स करने के अलावा SQL सर्वर में तालिका से JSON में जाने का कोई बेहतर तेज़ तरीका है?
+0

मध्यम परत के बारे में हमें और बताएं। यह इतना लंबा क्या ले रहा है? क्या यह संकलित कोड है? एक ऐसा एप्लिकेशन लिखना बहुत संभव होना चाहिए जो एक रिकॉर्डसेट को जेएसओएन में बदल देता है और इसमें पर्याप्त प्रदर्शन है। – ErikE

+2

मान लीजिए कि आप अपने विशेष पात्रों से ठीक से बचते हैं, यह करने योग्य है ... लेकिन ... आप क्यों? एसक्यूएल सर्वर एक भयानक स्ट्रिंग पार्सिंग इंजन है, और आपके पास एक अंतर्निहित एक्सएमएल इंजन है जो हमेशा अनुरूप एक्सएमएल को अपेक्षाकृत कुशल तरीके से थूक सकता है। –

+1

@EricE अधिकांश टेबल जेसन को बहुत जल्दी कनवर्ट करते हैं। यह केवल इसलिए हुआ क्योंकि हम फुल कैलेंडर के लिए एक टेबल पार्स कर रहे हैं। मध्य पार्स बस तालिका लेता है और स्ट्रिंग बनाने के लिए फ़ील्ड और पंक्तियों के माध्यम से चक्र के लिए एक foreach का उपयोग करता है। हम इसे तेजी से प्रदर्शन करने के लिए मध्य में कुछ चीजों को ठीक कर सकते हैं, लेकिन अगर हम एसक्यूएल करते हुए प्रक्रिया में एक अतिरिक्त कदम से बच सकते हैं ... क्यों नहीं? – davids

उत्तर

8

मैं व्यक्तिगत रूप से लगता है कि स्ट्रिंग परिवर्तन के इस प्रकार के लिए सबसे अच्छी जगह में प्रोग्राम कोड में है एक पूरी तरह से अभिव्यक्तिपूर्ण भाषा जिसमें कार्य है और संकलित किया जा सकता है। टी-एसक्यूएल में ऐसा करना अच्छा नहीं है। कार्यक्रम कोड में तेजी से कार्य हो सकते हैं जो उचित भागने से काम करते हैं।

  • जब आप भागों और आपके आवेदन के टुकड़े के नए संस्करण को तैनात है, जहां होने के लिए इस कार्यशीलता के लिए सबसे अच्छी जगह है:

    की चीजों के बारे में सोचने के लिए थोड़ा करते हैं?

  • यदि आपको अपना डेटाबेस (और इसकी सभी संग्रहीत प्रक्रियाओं) को पुनर्स्थापित करना है तो क्या यह नकारात्मक रूप से कुछ भी प्रभावित करेगा? यदि आप अपने वेब फ्रंट एंड के नए संस्करण को तैनात कर रहे हैं, तो जेएसओएन रूपांतरण डेटाबेस में बंधे हुए समस्याओं का कारण बन जाएगा?

  • आप पात्रों से कैसे बचेंगे? क्या आप कोई तिथियां भेज रहे हैं? किस प्रारूप में तार तार होंगे और वे दूसरे छोर पर वास्तविक तिथि ऑब्जेक्ट्स में कैसे परिवर्तित हो जाएंगे (यदि इसकी आवश्यकता है)?

  • यह साबित करने के लिए कि आप सही तरीके से काम कर रहे हैं, आप कैसे परीक्षण करेंगे (और स्वचालित परीक्षणों के साथ!) आप इसका परीक्षण कैसे करेंगे?

  • एसक्यूएल सर्वर यूडीएफ बहुत धीमा हो सकता है। क्या आप धीमे फ़ंक्शन का उपयोग करने के लिए सामग्री रखते हैं, या Replace(Replace(Replace(Replace(Value, '\', '\\'), '"', '\"'), '''', '\'''), Char(13), '\n') जैसे आपकी SQL कोड चीजों में स्पीड हैक के लिए? यूनिकोड, \u और \x से बचने के बारे में क्या? '</script>' को '<' + '/script>' में विभाजित करने के बारे में कैसे? (हो सकता है कि यह लागू न हो, लेकिन हो सकता है कि आप अपने JSON का उपयोग कैसे करें।) क्या आपकी टी-एसक्यूएल प्रक्रिया यह सब करने जा रही है, और अलग-अलग रिकॉर्डसेट के लिए पुन: प्रयोज्य हो, या आप इसे हर बार प्रत्येक बार फिर से लिखेंगे एसपी कि आपको जेएसओएन वापस करने की जरूरत है?

  • आपके पास केवल एक एसपी हो सकता है जिसे JSON वापस करने की आवश्यकता है। अभी के लिए। कुछ दिन, आप और अधिक हो सकता है। फिर यदि आपको कोई बग मिलती है, तो आपको इसे दो स्थानों पर ठीक करना होगा। या पांच। या ज्यादा।

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

स्पीड युक्तियाँ एक वेब अनुप्रयोग

  1. में हैंडलिंग सुनिश्चित करें कि आपके वेब स्ट्रिंग संयोजन कोड Schlemiel the Painter's Algorithm से ग्रस्त न हो। जेएसओएन जेनरेट किया गया है (Response.Write) के रूप में सीधे आउटपुट बफर को सीधे लिखें या उचित स्ट्रिंगबिल्डर ऑब्जेक्ट का उपयोग करें, या जेएसओएन के हिस्सों को सरणी में लिखें और बाद में इसमें शामिल हों। सादे वेनिला कॉन्सटेनेशन को लंबे और लंबे स्ट्रिंग पर और अधिक न करें।
  2. जितना संभव हो उतना कम से कम ऑब्जेक्ट ऑब्जेक्ट्स। मुझे आपकी सर्वर-साइड भाषा नहीं पता है, लेकिन यदि यह एएसपी क्लासिक होने के लिए होता है, तो फ़ील्ड नामों का उपयोग न करें - या तो एक चर में या कम से कम उपयोग पूर्णांक फ़ील्ड इंडेक्स में प्रत्येक फ़ील्ड का संदर्भ प्राप्त करें। एक लूप के अंदर अपने नाम के आधार पर एक फ़ील्ड को डीरफ्रेंस करना (अधिक) खराब प्रदर्शन है।
  3. पूर्व-निर्मित पुस्तकालयों का उपयोग करें। जब आप किसी कोशिश की गई और सही लाइब्रेरी का उपयोग कर सकते हैं तो अपना खुद का रोल न करें। प्रदर्शन आपके लिए बराबर या बेहतर होना चाहिए और (सबसे महत्वपूर्ण बात यह है कि यह परीक्षण और सही होगा।
  4. यदि आप ऐसा करने में समय बिताने जा रहे हैं, तो इसे किसी भी रिकॉर्डसेट को परिवर्तित करने के लिए पर्याप्त सार बनाएं, न केवल आपके पास।
  5. संकलित कोड का उपयोग करें। जब संकलित किया जाता है, तो आप हमेशा सबसे तेज़ कोड प्राप्त कर सकते हैं, इसका अर्थ नहीं है। यदि आप पहचानते हैं कि जेएसओएन-रूपांतरण दिनचर्या वास्तव में बाधा हैं (और आपको इसे वास्तविक साबित करना चाहिए, अनुमान न करें) तो कोड को संकलित करने वाले किसी चीज़ में प्राप्त करें।
  6. स्ट्रिंग लंबाई कम करें। यह एक बड़ा नहीं है, लेकिन यदि संभव हो तो कई पत्रों के बजाय एक-अक्षर जेसन नामों का उपयोग करें। एक विशाल रिकॉर्डसेट के लिए यह दोनों सिरों पर बचत तक जोड़ देगा।
  7. सुनिश्चित करें कि यह GZipped है। यह सर्वर-साइड सुधार इतना नहीं है, लेकिन मैं पूर्ण होने के बिना JSON प्रदर्शन का उल्लेख नहीं कर सका। JSON

    में

पासिंग तिथियां क्या मेरा सुझाव है एक अलग JSON स्कीमा (अपने आप JSON में, आभासी recordset की संरचना को परिभाषित करने का पालन करने) का प्रयोग है। इस स्कीमा को "रिकॉर्डसेट" के लिए हेडर के रूप में भेजा जा सकता है, या इसे पहले से ही पृष्ठ में लोड किया जा सकता है (बेस जावास्क्रिप्ट फाइलों में शामिल) ताकि इसे हर बार भेजा जाना पड़े। फिर, अपने JSON पार्स कॉलबैक (या अंतिम परिणामी ऑब्जेक्ट पर पोस्ट-कॉलबैक) में वर्तमान कॉलम के लिए स्कीमा देखें और आवश्यकतानुसार रूपांतरण करें। आप ECMAScript 5 strict mode में आईएसओ प्रारूप का उपयोग करने पर विचार कर सकते हैं, वहां बेहतर दिनांक समर्थन होना चाहिए और डेटा प्रारूप को बदलने के बिना आपके कोड को सरलीकृत किया जा सकता है (और एक साधारण ऑब्जेक्ट डिटेक्ट आपको इस कोड का उपयोग करने वाले किसी भी ब्राउज़र के लिए उपयोग करने दे सकता है):

दिनांक

तिथियां अब दोनों पार्स करने और outputting आईएसओ स्वरूपित दिनांकों में सक्षम हैं।

दिनांक निर्माता अब तारीख को पार्स करने का प्रयास करता है जैसे कि यह आईएसओ-स्वरूपित था, पहले, फिर यह स्वीकार किए जाने वाले अन्य इनपुट पर चलता है।

इसके अतिरिक्त, दिनांक ऑब्जेक्ट्स में अब एक नई .toISOString() विधि है जो किसी ISO प्रारूप में दिनांक को आउटपुट करती है। var date = new date ("2009-05-21T16: 06: 05.000Z");

प्रिंट (date.toISOString()); // 200 9 -21-21 टी 16: 06: 05.000Z

+1

+1 मेरी तुलना में बेहतर है। मैं अपना जवाब हटा दूंगा। –

+1

आप कुछ बहुत अच्छे अंक उठाते हैं, और एक आकर्षक तर्क देते हैं। यह ज्यादातर स्थितियों के लिए सही समाधान नहीं हो सकता है। हम उपर्युक्त मुद्दों के लिए तिथियों और अन्य कार्य-आसपास जैसी चीजों के लिए एक मानक प्रारूप की योजना बना रहे थे, लेकिन वे बस ... काम करते थे। एमएस को सिर्फ एक JSON प्रारूप जोड़ने की आवश्यकता है जैसे कि वे एक एक्सएमएल प्रारूप प्रदान करते हैं। – davids

+0

@ डेविड क्या JSON में गुजरने वाली तिथियों के बारे में मेरी अतिरिक्त जानकारी सहायक है? – ErikE

3

मुझे लगता है कि जिस तरह से आप कर रहे हैं (contatenating)

आप JSON.net उपयोग करता है और एक varchar देता है कि एक CLR एसक्यूएल समारोह बनाने की कोशिश कर सकते नहीं मारूंगा।

यहाँ देखें SQL CLR कार्य बनाने का तरीका: http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.80).aspx

इस (अपरीक्षित कोड) की तरह कुछ

[Microsoft.SqlServer.Server.SqlFunction] 
public static SqlString MyFunctionName(int id) { 
    // Put your code here (maybe find the object you want to serialize using the id passed?) 
    using (var cn = new SqlConnection("context connection=true")) { 
     //get your data into an object 
     var myObject = new {Name = "My Name"}; 
     return new SqlString(Newtonsoft.Json.JsonConvert.SerializeObject(myObject)); 
    } 
} 
+0

सीएलआर एसक्यूएल फ़ंक्शन में json.net का उपयोग मध्यम परत में करने से अलग कैसे है? मैंने कभी भी सीएलआर एसक्यूएल फ़ंक्शन का उपयोग नहीं किया है, इसलिए यह एक मूर्ख सवाल हो सकता है, लेकिन नतीजा इसके बारे में नहीं होगा? – davids

+0

आप वस्तुओं से SELECT MyDb.dbo.ConvertToJson (आईडी) जैसे कुछ करने में सक्षम होंगे ताकि आपके पास प्रत्यक्ष डीबी कॉल हो। – turtlepick

+0

याद रखें कि JSON वास्तव में कठिन और विशेष रूप से दिनांक और समय फ़ील्ड के साथ हो सकता है (आप विशेष वर्णों और सभी के लिए भी खाता लेना चाहेंगे ...) – turtlepick

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