आपके आवेदन में sql बनाम में गणना करने के पेशेवरों और विपक्ष क्या हैं


154

shopkeeper तालिका में निम्नलिखित क्षेत्र हैं:

id (bigint),amount (numeric(19,2)),createddate (timestamp)

मान लीजिए, मेरे पास उपरोक्त तालिका है। मैं कल के लिए रिकॉर्ड प्राप्त करना चाहता हूं और सेंट के लिए मुद्रित राशि होने से एक रिपोर्ट उत्पन्न करता हूं।

मेरे जावा एप्लिकेशन में गणना करने और एक सरल क्वेरी निष्पादित करने का एक तरीका है

Date previousDate ;// $1 calculate in application

Date todayDate;// $2 calculate in application

select amount where createddate between $1 and $2 

और फिर रिकॉर्ड के माध्यम से लूप करें और मेरे जावा एप्लिकेशन में सेंट में राशि परिवर्तित करें और रिपोर्ट उत्पन्न करें

एक अन्य तरीका स्वयं sql क्वेरी में गणना करने जैसा है:

select cast(amount * 100 as int) as "Cents"
from shopkeeper  where createddate  between date_trunc('day', now()) - interval '1 day'  and  date_trunc('day', now())

और फिर रिकॉर्ड के माध्यम से लूप करें और रिपोर्ट जनरेट करें

एक तरह से, मेरा सारा प्रसंस्करण जावा एप्लिकेशन में किया जाता है और एक साधारण क्वेरी निकाल दी जाती है। अन्य मामले में सभी रूपांतरण और गणना Sql क्वेरी में की जाती है।

उपरोक्त उपयोग का मामला सिर्फ एक उदाहरण है, वास्तविक परिदृश्य में एक तालिका में कई स्तंभ हो सकते हैं जिन्हें समान प्रकार के प्रसंस्करण की आवश्यकता होती है।

क्या आप मुझे बता सकते हैं कि प्रदर्शन और अन्य पहलुओं के संदर्भ में कौन सा दृष्टिकोण बेहतर है और क्यों?


2
तिथि की गणनाओं का कोई प्रभाव नहीं पड़ेगा - यह मानकर कि आपका sql इंजन वास्तव में केवल एक बार ही आपकी तारीखों की गणना करेगा। आपके आवेदन में उन्हें परिभाषित करने से सही अर्थ निकलता है, क्योंकि वे किसी भी बिंदु पर वहाँ परिभाषित किए जाएंगे, चाहे वह रिपोर्ट शीर्षक या अन्य चीजों के लिए हो। इस मामले में मूल्य को 100 से गुणा करना किसी भी स्तर पर किया जा सकता है, क्योंकि आप रेंडरिंग के लिए वैसे भी उन पंक्तियों के माध्यम से लूपिंग करेंगे और * 100 के सामने के सिवाय किसी भी स्तर पर धीमे होने की संभावना नहीं है। या तो मामले में आपकी गणना न्यूनतम है और आसपास के संचालन से बौना है, प्रदर्शन चिंता का विषय नहीं है।
मुर्दाघर।

जवाबों:


206

यह बहुत सारे कारकों पर निर्भर करता है - लेकिन सबसे महत्वपूर्ण:

  • गणना की जटिलता (ऐप-सर्वर पर जटिल crunching कर पसंद करते हैं, कि तराजू के बाद से बाहर , बल्कि एक डाटाबेस सर्वर, से जो मापता अप )
  • डेटा की मात्रा (यदि आपको बहुत अधिक डेटा एक्सेस / एग्रीगेट करने की आवश्यकता है, तो इसे db सर्वर पर करने से बैंडविड्थ की बचत होगी, और डिस्क io यदि एग्रीगेट इंडेक्स के अंदर किया जा सकता है)
  • सुविधा (एसक्यूएल जटिल काम के लिए सबसे अच्छी भाषा नहीं है - विशेष रूप से प्रक्रियात्मक काम के लिए महान नहीं है, लेकिन सेट-आधारित काम के लिए बहुत अच्छा है; घटिया त्रुटि-हैंडलिंग, हालांकि)

हमेशा की तरह, अगर तुम करते हो , एप्लिकेशन-सर्वर से डेटा को वापस लाने के स्तंभों और पंक्तियों को न्यूनतम अपने लाभ के लिए किया जाएगा। यह सुनिश्चित करना कि क्वेरी ट्यून की गई है और उचित रूप से अनुक्रमित दोनों परिदृश्य में मदद करेंगे।

अपना ध्यान दें:

और फिर रिकॉर्ड के माध्यम से लूप

रिकॉर्ड्स के माध्यम से लूपिंग लगभग हमेशा गलत काम करता है - यह एक सेट-आधारित ऑपरेशन लिखना पसंद किया जाता है।

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

यह भी विचार करें: यदि यह कम्प्यूटेशनल रूप से महंगा है, तो क्या इसे कहीं कैश किया जा सकता है?

यदि आप एक सटीक "जो बेहतर है" चाहते हैं; इसे दोनों तरीकों से कोड करें और इसकी तुलना करें (यह देखते हुए कि या तो पहले मसौदे की संभावना 100% नहीं है)। लेकिन उस के लिए विशिष्ट उपयोग में कारक: अगर, वास्तविकता में, इसे एक ही बार में 5 बार (अलग-अलग) कहा जा रहा है, तो अनुकरण करें कि: इनमें से केवल 1 "इन 1 बनाम 1" की तुलना न करें।


लूपिंग अधिक या कम "पंक्ति-ए-ए-टाइम" प्रसंस्करण को दर्शाता है। और इसका मतलब है कि 2 * नेटवर्क विलंबता और चार संदर्भ स्विच राउंड ट्रिप। हाँ: यह महंगा है। "देशी" डीबीएमएस ऑपरेशन डिस्क-आई / ओ (सिस्टम कॉल) को कम करने के लिए सभी कड़ी मेहनत करता है लेकिन सिस्टम कॉल प्रति एक पंक्ति से अधिक लाने का प्रबंधन करता है। एक समय में रो कम से कम चार सिस्टम कॉल लेता है ।
Wildplasser

@wildplasser आवश्यक नहीं; सर्वर उन पंक्तियों को स्ट्रीम कर सकता है, जिनका आप उपभोग करते हैं जैसे वे आते हैं - एक "रीडर" रूपक असामान्य नहीं है।
मार्क Gravell

1
@ मर्केल केवेल: ठीक है, यह निर्भर करता है। इस मामले में जहां एक आवेदन कार्यक्रम का पदचिह्न केवल एक तार्किक रिकॉर्ड है, यह कम या ज्यादा ठीक है। लेकिन मुझे पता है कि "फ्रेमवर्क" के अधिकांश स्टार्टअप में सभी रिकॉर्डों को चूसना, और उन्हें एक-एक करके आग देना है। ताला लगाना एक और नुकसान है।
Wildplasser

मुझे लगता है कि अंगूठे का एक अच्छा नियम है: डेटा की SQL सर्वर पंक्तियों से वापस न लाएं जिनकी आपको अंततः आवश्यकता नहीं है। उदाहरण के लिए, यदि आपको कुल संचालन करना है, तो वे संभवतः SQL में हैं। तालिकाओं या उपश्रेणियों के बीच जुड़ता है? एसक्यूएल। यह भी दृष्टिकोण है कि हम बैज के साथ उपयोग करते हैं, और, अब तक, हम पैमाने के साथ मुकाबला कर रहे हैं :-)
स्किलिवज़

1
@zink जो एक सेट-आधारित ऑपरेशन होगा। उस परिदृश्य में आप लूप कोड नहीं लिखते हैं - यह एक कार्यान्वयन विवरण है। "लूपिंग" से मेरा मतलब स्पष्ट छोरों से है, उदाहरण के लिए एक कर्सर
मार्क ग्रेवेल

86

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

जहां तक PostgreSQL का सवाल है, आप सर्वर पर लगभग कुछ भी कर सकते हैं, काफी कुशलता से। जटिल प्रश्नों पर RDBMS एक्सेल करता है। प्रक्रियात्मक आवश्यकताओं के लिए आप विभिन्न प्रकार की सर्वर-साइड स्क्रिप्ट भाषाओं में से चुन सकते हैं : tcl, python, perl और कई और। अधिकतर मैं PL / pgSQL का उपयोग करता हूँ , हालाँकि।

सबसे बड़ा मामला परिदृश्य बार-बार बड़े सेट की हर एक पंक्ति के लिए सर्वर पर जाना होगा। (यह एक समय में एक टन अयस्क की शिपिंग जैसा होगा।)

दूसरी पंक्ति में , यदि आप प्रश्नों का एक कैस्केड भेजते हैं, तो प्रत्येक पहले के आधार पर, जबकि यह सब सर्वर पर एक प्रश्न या प्रक्रिया में किया जा सकता है। (यह एक अलग जहाज, क्रमिक रूप से सोने और जवाहरात के प्रत्येक शिपिंग की तरह है।)

ऐप और सर्वर के बीच आगे-पीछे जाना महंगा है। सर्वर और क्लाइंट के लिए। उस पर कटौती करने की कोशिश करें, और आप जीतेंगे - एर्गो: जहां आवश्यक हो सर्वर साइड प्रक्रियाओं और / या परिष्कृत एसक्यूएल का उपयोग करें।

हमने अभी एक परियोजना पूरी की है जहाँ हमने लगभग सभी जटिल प्रश्नों को पोस्टग्रेज फ़ंक्शंस में पैक किया है। एप्लिकेशन मापदंडों को सौंपता है और इसके लिए आवश्यक डेटासेट प्राप्त करता है। तेज, स्वच्छ, सरल (ऐप डेवलपर के लिए), आई / ओ कम से कम ... एक कम कार्बन पदचिह्न के साथ एक चमकदार हार।


12
मैं अन्य डेवलपर्स के साथ डिजाइन निर्णय लेने के लिए इस सादृश्य का उपयोग करने के बारे में सतर्क रहूंगा। एनालॉग्स एक तार्किक की तुलना में एक बयानबाजी डिवाइस के अधिक हैं। अन्य कारकों में, यह एक सुनार के लिए सुनहरा अयस्क जहाज करने की तुलना में एक ऐप सर्वर पर डेटा जहाज करने के लिए बहुत सस्ता है।
डग

3
आप अयस्क या सोना भेज देंगे जो सस्ता है, अगर आपके पास अयस्क को सोने में बदलने की तकनीक नहीं है, या यह महंगा है (क्योंकि खनिक इन अन्य श्रमिकों को मारना चाहते हैं), आप इसे दूसरे स्थान पर भेज देंगे, शायद इसमें सुनार और खनिक के बीच, खासकर यदि आपके पास अधिक है तो एक सुनार।
Dainius

1
ठीक से मैं सहमत हूं, मुझे नहीं लगता कि SQL @a_horse_with_no_name में लूप आधारित गणना करना हमेशा बुरा होता है, कभी-कभी इसे वैसे भी करना पड़ता है, मैं तब गणना करना चाहूंगा जब डेटा को इरविन के रूपक के रूप में संकेत दिया जाता है। या जब डेटा वापस लाया जाता है तो आपको इसे एक लागत पर दोहराना होता है।
zinking

-1 क्योंकि यह एकतरफा तर्क है, व्यापार-बंदियों की उपेक्षा करता है, और विरोधी पक्ष के सर्वोत्तम मामले पर विचार करने और खंडन करने के बजाय विरोधी पक्ष के लिए एक पुआल आदमी को स्थापित करता है। "ऐप और सर्वर के बीच आगे और पीछे जाना महंगा है" - बिल्कुल: लेकिन यह केवल एक चीज नहीं है जो महंगी है, और विभिन्न खर्चों को एक दूसरे के खिलाफ तौलना चाहिए। यह पता चल सकता है कि "परिष्कृत SQL" प्रश्न या संग्रहीत कार्यविधियाँ किसी विशेष मामले के लिए सबसे अच्छी हैं; लेकिन उस तरह का निर्धारण करते समय मामले के विवरण को आम तौर पर ध्यान में रखा जाना चाहिए।
yfeldblum

शांत सादृश्य लेकिन दुर्भाग्य से यह गलत धारणाओं पर आधारित है। शिपिंग गोल्ड अयस्क बहुत आम है। सोने की स्ट्रिपिंग का अनुपात लगभग 1: 1 (सोने की बर्बादी) है लेकिन इसे ऑफसाइट प्रोसेस करने के लिए अक्सर सस्ता होता है, जहां बेहतर उपकरण और कारीगरी की गुणवत्ता उपलब्ध है। शिपमेंट के आकार के आधार पर, प्रसंस्करण दक्षता में 0.1% की वृद्धि से राजस्व के सापेक्ष वृद्धि (दोगुनी शिपिंग कीमत के बावजूद) की अनुमति मिल सकती है - क्योंकि इन दिनों सोना काफी महंगा है। उदाहरण के लिए लोहे की तरह अन्य अयस्कों को भी आम तौर पर भेज दिया जाता है (लोहे का स्ट्रिपिंग अनुपात लगभग 60% है!)।
क्रिस कोस्टन

18

इस मामले में आप शायद एसक्यूएल में गणना करने से थोड़ा बेहतर हैं क्योंकि डेटाबेस इंजन में जावा की तुलना में अधिक कुशल दशमलव अंकगणित रूटीन होने की संभावना है।

आमतौर पर हालांकि पंक्ति स्तर की गणना के लिए बहुत अंतर नहीं होता है।

जहां इससे फर्क पड़ता है:

  • एसयूएम (एवीजी, एवीजी (), एमआईएन (), मैक्स () जैसे एग्रिगेट कैलकुलेशन यहाँ डेटाबेस इंप्लिमेंट जावा कार्यान्वयन की तुलना में तेजी से परिमाण का क्रम होगा।
  • कहीं भी गणना पंक्तियों को फ़िल्टर करने के लिए उपयोग की जाती है। DB में फ़िल्टर करना किसी पंक्ति को पढ़ने और फिर उसे छोड़ने की तुलना में बहुत अधिक कुशल है।

12

डेटा एक्सेस लॉजिक के कुछ हिस्सों को SQL में क्या किया जाना चाहिए और आपके एप्लिकेशन में किन हिस्सों में प्रदर्शन किया जाना चाहिए, इस संबंध में कोई काला / सफेद नहीं है। मुझे मार्क ग्रेवेल का शब्दांकन पसंद है , जिसके बीच अंतर है

  • जटिल गणना
  • डेटा-गहन गणना

SQL की शक्ति और अभिव्यक्तता को बहुत कम आंका जाता है। खिड़की के कार्यों की शुरुआत के बाद से , डेटाबेस में बहुत ही गैर-कड़ाई से सेट-उन्मुख गणना आसानी से और सुरुचिपूर्ण ढंग से की जा सकती है।

समग्र अनुप्रयोग वास्तुकला की परवाह किए बिना, अंगूठे के तीन नियमों का हमेशा पालन किया जाना चाहिए:

  • डेटाबेस और एप्लिकेशन के बीच स्थानांतरित डेटा की मात्रा को पतला रखें (DB में सामान की गणना के पक्ष में)
  • डेटाबेस से डिस्क से लोड किए गए डेटा की मात्रा को पतला रखें (अनावश्यक डेटा एक्सेस से बचने के लिए डेटाबेस को स्टेटमेंट ऑप्टिमाइज़ करने के पक्ष में)
  • जटिल, समवर्ती गणनाओं के साथ अपनी सीपीयू सीमाओं के लिए डेटाबेस को धक्का न दें (आवेदन मेमोरी में डेटा खींचने और वहां गणना करने के पक्ष में)

मेरे अनुभव में, एक सभ्य DBA और आपके सभ्य डेटाबेस के बारे में कुछ अच्छे ज्ञान के साथ, आप बहुत जल्द ही अपने DBs CPU सीमा में नहीं चलेंगे।

कुछ और पढ़ने से जहां इन बातों को समझाया गया है:


2

सामान्य तौर पर एसक्यूएल में काम करते हैं अगर वहाँ संभावना है कि अन्य मॉड्यूल या उसी या अन्य परियोजनाओं में घटक उन परिणामों को प्राप्त करने की आवश्यकता होगी। एक परमाणु संचालन किया गया सर्वर साइड भी बेहतर है क्योंकि आपको आगे की प्रक्रिया के लिए अंतिम मान प्राप्त करने के लिए किसी भी डीबी प्रबंधन टूल से संग्रहीत खरीद को आमंत्रित करना होगा।

कुछ मामलों में यह लागू नहीं होता है लेकिन जब यह होता है तो यह समझ में आता है। सामान्य तौर पर db बॉक्स में सबसे अच्छा हार्डवेयर और प्रदर्शन होता है।


पुन: प्रयोज्य किसी भी स्तर पर मौजूद हो सकता है और एसक्यूएल में अधिक गणना करने के लिए एक कारण (प्रदर्शन बुद्धिमान) नहीं है। "सामान्य तौर पर db बॉक्स": यह गलत है और इसके अलावा, जैसा कि marc gravell ने कहा, स्केलिंग उसी तरह से काम नहीं करती है। अधिकांश डेटाबेस को शालीनता से चलाने के लिए बहुत कम हार्डवेयर की आवश्यकता होती है, और प्रदर्शन पैटर्न का अनुप्रयोग सर्वर के साथ बहुत कम होता है (यानी मैं अपने बजट के 2/3% को किसी SQL सर्वर के लिए Godlike IO पर खर्च करूंगा जबकि मैं अधिक खर्च नहीं करूंगा एक appserver के भंडारण ढेर के लिए कुछ सैकड़ों की तुलना में)।
मुर्दाघर।

1

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

आइए इसके बारे में दो चरणों में सोचते हैं: (1) ओएलटीपी (रिकॉर्ड की छोटी संख्या) लेनदेन। (2) OLAP (कई रिकॉर्ड का लंबा स्कैन)।

ओएलटीपी मामले में, यदि आप तेज़ होना चाहते हैं (10k - 100k लेनदेन प्रति सेकंड), तो आपको डेटाबेस से कुंडी, ताला और मृत लॉक विवाद को हटाना होगा। इसका मतलब है कि आपको लेन-देन में लंबे स्टालों को खत्म करने की आवश्यकता है: क्लाइंट से प्रोसेसिंग को स्थानांतरित करने के लिए क्लाइंट से DB तक की गोल यात्राएं एक ऐसा लंबा स्टाल है। आप लंबे समय तक लेन-देन नहीं कर सकते हैं (परमाणु पढ़ने / अद्यतन करने के लिए) और बहुत अधिक थ्रूपुट हैं।

पुन: क्षैतिज स्केलिंग। आधुनिक डेटाबेस पैमाने क्षैतिज रूप से। वे सिस्टम हा और फॉल्ट टॉलरेंस को पहले से ही लागू करते हैं। इसका लाभ उठाएं और अपने आवेदन स्थान को सरल बनाने का प्रयास करें।

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


0

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

  1. यदि आप डेटाबेस sql के माध्यम से कुछ सीधा प्राप्त कर सकते हैं तो बेहतर है कि इसके लिए db ज्यादा बेहतर प्रदर्शन करें और वहां और फिर परिणाम लाने के लिए संगणना करें। हालाँकि यदि वास्तविक गणना में यहाँ और वहाँ से बहुत अधिक गणना की आवश्यकता होती है तो आप आवेदन कोड के साथ जा सकते हैं। क्यों? क्योंकि ज्यादातर मामलों में लैंडस्केप की तरह लूपिंग को सबसे अच्छी तरह से नियंत्रित नहीं किया जाता है, इसलिए इन चीजों के लिए बेहतर डिजाइन किए गए हैं।
  2. यदि कई स्थानों से समान गणना की आवश्यकता होती है, तो स्पष्ट रूप से डीबी के अंत में गणना कोड को एक ही स्थान पर रखना बेहतर होगा।
  3. यदि कई अलग-अलग प्रश्नों के माध्यम से अंतिम परिणाम प्राप्त करने के लिए बहुत सारी गणनाएं की जाती हैं, तो db समाप्ति के लिए भी जाएं क्योंकि आप बैकएंड से परिणाम प्राप्त करने और फिर उन्हें सामने से गणना करने से बेहतर प्रदर्शन करने के लिए एक ही कोड को संग्रहीत कार्यविधि में रख सकते हैं समाप्त।

कई अन्य पहलू हैं जो आप यह तय करने से पहले सोच सकते हैं कि कोड कहां रखा जाए। एक धारणा पूरी तरह से गलत है - सब कुछ जावा (ऐप कोड) में सबसे अच्छा किया जा सकता है और / या सब कुछ डीबी (एसक्यूएल कोड) द्वारा किया जाना सबसे अच्छा है।


0

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

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


0

महत्वपूर्ण रूप से, "प्रदर्शन" को परिभाषित नहीं किया गया है।

जो मेरे लिए सबसे ज्यादा मायने रखता है वह है डेवलपर का समय।

SQL क्वेरी लिखें। यदि यह बहुत धीमा है या DB एक अड़चन बन जाता है, तो पुनर्विचार करें। उस समय तक, आप दो दृष्टिकोणों को बेंचमार्क कर सकेंगे और अपने सेटअप (हार्डवेयर और जो कुछ भी आप पर टिके हैं) से संबंधित वास्तविक डेटा के आधार पर अपना निर्णय ले सकेंगे।


0

मुझे विश्वास नहीं है कि विशिष्ट अंतर और बेंचमार्क के बिना प्रदर्शन के अंतर को तर्क दिया जा सकता है, लेकिन मुझे एक और लेना है:

जो आप बेहतर बनाए रख सकते हैं? उदाहरण के लिए, आप अपने फ्रंट-एंड को जावा से फ्लैश, या एचटीएमएल 5, या सी ++, या कुछ और पर स्विच करना चाह सकते हैं। इस तरह के एक परिवर्तन के माध्यम से बड़ी संख्या में कार्यक्रम हुए हैं, या यहां तक ​​कि एक से अधिक भाषाओं में मौजूद हैं, क्योंकि उन्हें कई उपकरणों पर काम करने की आवश्यकता है।

यहां तक ​​कि अगर आपके पास एक उचित मध्य परत है (दिए गए उदाहरण से, ऐसा लगता है कि ऐसा नहीं है), वह परत बदल सकती है और JBoss रूबी / रेल बन सकती है।

दूसरी ओर, यह संभावना नहीं है कि आप SQL-बैकेंड को किसी ऐसी चीज़ से बदल देंगे जो SQL के साथ संबंधपरक DB नहीं है और यहां तक ​​कि यदि आप करते हैं, तो आपको किसी भी तरह खरोंच से फ्रंट-एंड को फिर से लिखना होगा, इसलिए बिंदु मूट है।

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


यदि आप jboss से रूबी में बदलते हैं, तो यह बहुत संभावना है कि आप db को बदल देंगे (और आपको इन गणनाओं को वैसे भी अपनाने की आवश्यकता होगी) और यह संभावना नहीं है कि आप nosql की तरह कुछ और बदल सकते हैं।
Dainius

0

यह सरल करने के लिए कि इसका उत्तर लोड संतुलन को देखने के लिए कैसे होगा। आप उस भार को डालना चाहते हैं जहां आपके पास सबसे अधिक क्षमता है (यदि यह कोई मतलब है)। अधिकांश प्रणालियों में यह SQL सर्वर है जो जल्दी से एक अड़चन बन जाता है इसलिए संभवतः इसका उत्तर यह है कि आप नहीं चाहते हैं कि SQL एक औंस से अधिक काम कर सके।

अधिकांश आर्किटेक्चर में भी यह SQL सर्वर (s) है जो सिस्टम के कोर और बाहरी सिस्टम को बनाते हैं जो कि जुड़ जाते हैं।

लेकिन ऊपर दिया गया गणित इतना तुच्छ है कि जब तक आप अपने सिस्टम को सबसे अच्छी जगह पर सीमित करने के लिए जोर नहीं दे रहे हैं, जहां आप इसे रखना चाहते हैं। यदि गणित तुच्छ नहीं था, जैसे कि दूरी की गणना के लिए पाप / कॉस / टैन की गणना करना, तो प्रयास गैर-तुच्छ हो सकता है और सावधानीपूर्वक योजना और परीक्षण की आवश्यकता होती है।


0

इस प्रश्न के अन्य उत्तर दिलचस्प हैं। हैरानी की बात है कि किसी ने भी आपके सवाल का जवाब नहीं दिया। आप सोच रहे हैं:

  1. क्या क्वेरी में सेंट को डालना बेहतर है? मुझे नहीं लगता है कि कलाकारों के लिए कास्ट आपकी क्वेरी में कुछ भी जोड़ता है।
  2. क्या क्वेरी में अब () का उपयोग करना बेहतर है? मैं उन्हें क्वेरी में गणना करने के बजाय क्वेरी में दिनांक देना पसंद करूंगा।

अधिक जानकारी: प्रश्न के लिए आप यह सुनिश्चित करना चाहते हैं कि भिन्न को बिना गोल त्रुटियों के कार्य करना है। मुझे लगता है कि संख्यात्मक 19,2 पैसे के लिए उचित है और दूसरे मामले में पूर्णांक ठीक हैं। पैसे के लिए फ्लोट का उपयोग करना इस कारण से गलत है।

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


0

मुझे इस प्रश्न का समाधान करने के लिए एक वास्तविक उदाहरण लेना चाहिए

मुझे अपने ohlc डेटा पर एक भारित चलती औसत की गणना करने की आवश्यकता है, मेरे पास ऐसा करने के लिए प्रत्येक प्रतीक के साथ लगभग 134000 मोमबत्तियाँ हैं।

  1. विकल्प 1 इसे पायथन / नोड आदि आदि में करें
  2. विकल्प 2 इसे SQL में ही करें!

इनमे से कौन बेहतर है?

  • अगर मुझे पायथन में ऐसा करना पड़ता है, तो अनिवार्य रूप से, मुझे सबसे खराब स्थिति में सभी संग्रहित रिकॉर्ड लाने होंगे, संगणना प्रदर्शन करना होगा और सब कुछ वापस बचाना होगा, जो मेरी राय में IO का बहुत बड़ा अपव्यय है।
  • भारित मूविंग औसत परिवर्तन हर बार आपको एक नया मोमबत्ती मिलता है जिसका अर्थ है कि मैं नियमित अंतराल पर भारी मात्रा में IO कर रहा हूं जो मेरे संकेत में एक अच्छी राय नहीं है
  • SQL में, मुझे बस इतना करना है कि शायद एक ट्रिगर लिखें जो सब कुछ गणना करता है और संग्रहीत करता है, इसलिए केवल प्रत्येक जोड़ी के लिए हर बार अंतिम WMA मूल्यों को लाने की आवश्यकता है और यह बहुत अधिक कुशल है

आवश्यकताएँ

  • अगर मुझे हर मोमबत्ती के लिए डब्ल्यूएमए की गणना करना और उसे स्टोर करना था, तो मैं इसे पायथन पर करूंगा
  • लेकिन जब से मुझे केवल अंतिम मूल्य की आवश्यकता है, SQL पायथन की तुलना में बहुत तेज है

आपको कुछ प्रोत्साहन देने के लिए, यह एक भारित चलती औसत करने के लिए पायथन संस्करण है

WMA कोड के माध्यम से किया गया

import psycopg2
import psycopg2.extras
from talib import func
import timeit
import numpy as np
with psycopg2.connect('dbname=xyz user=xyz') as conn:
with conn.cursor() as cur:
t0 = timeit.default_timer()
cur.execute('select distinct symbol from ohlc_900 order by symbol')
for symbol in cur.fetchall():
cur.execute('select c from ohlc_900 where symbol = %s order by ts', symbol)
ohlc = np.array(cur.fetchall(), dtype = ([('c', 'f8')]))
wma = func.WMA(ohlc['c'], 10)
# print(*symbol, wma[-1])
print(timeit.default_timer() - t0)
conn.close()

SQL के माध्यम से WMA

"""
if the period is 10
then we need 9 previous candles or 15 x 9 = 135 mins on the interval department
we also need to start counting at row number - (count in that group - 10)
For example if AAPL had 134 coins and current row number was 125
weight at that row will be weight = 125 - (134 - 10) = 1
10 period WMA calculations
Row no Weight c
125 1
126 2
127 3
128 4
129 5
130 6
131 7
132 8
133 9
134 10
"""
query2 = """
WITH
condition(sym, maxts, cnt) as (
select symbol, max(ts), count(symbol) from ohlc_900 group by symbol
),
cte as (
select symbol, ts,
case when cnt >= 10 and ts >= maxts - interval '135 mins'
then (row_number() over (partition by symbol order by ts) - (cnt - 10)) * c
else null
end as weighted_close
from ohlc_900
INNER JOIN condition
ON symbol = sym
WINDOW
w as (partition by symbol order by ts rows between 9 preceding and current row)
)
select symbol, sum(weighted_close)/55 as wma
from cte
WHERE weighted_close is NOT NULL
GROUP by symbol ORDER BY symbol
"""
with psycopg2.connect('dbname=xyz user=xyz') as conn:
with conn.cursor() as cur:
t0 = timeit.default_timer()
cur.execute(query2)
# for i in cur.fetchall():
# print(*i)
print(timeit.default_timer() - t0)
conn.close()

मानो या ना मानो, क्वेरी शुद्ध अजगर संस्करण से अधिक तेजी से चलती है एक वजन बढ़ रहा है! मैं उस प्रश्न को लिखित रूप में चरण दर चरण आगे बढ़ाता गया ताकि उसमें लटका रहे और आप ठीक कर पाएंगे

गति

0.42141127300055814 सेकंड पायथन

0.23801879299935536 सेकंड एसक्यूएल

मेरे पास अपने 1000 सर्वरों के बीच विभाजित किए गए डेटाबेस में 134000 नकली OHLC रिकॉर्ड हैं ताकि SQL अपने ऐप सर्वर को बेहतर बना सके, इसका एक उदाहरण है


1
हालाँकि, यदि आपको इसे लाखों बार जल्दी से जल्दी करने की आवश्यकता है, तो यह डीबी प्रतिकृतियों की तुलना में समानांतर पायथन ऐप को स्पॉन्ट करना बहुत आसान है। जब तक एसक्यूएल पर एक निश्चित पैमाने पर अधिक झुकाव निश्चित रूप से तेज / सस्ता नहीं होता है, लेकिन आखिरकार एक टिपिंग बिंदु होता है जब आपके आवेदन में इस गणना को करना बेहतर होता है।
लेनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.