SQL घोषणात्मक है?


22

मैं पूछता हूँ क्योंकि SQL राशि में मेरे द्वारा देखे गए कई प्रश्न हैं: "यह धीमा है। मैं इसे कैसे गति दूं"? या ट्यूटोरियल कह रहे हैं "इस तरह से करें और उस तरह से नहीं जैसे कि यह तेज है"।

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

यदि आप उपयोग करते हैं in, तो एसक्यूएल इंजन को इसकी परवाह नहीं करनी चाहिए , existsया joinयदि यह वास्तव में घोषित है , तो क्या यह आपको उचित समय में सही जवाब नहीं देना चाहिए यदि तीन तरीकों में से कोई भी संभव हो? यह अंतिम उदाहरण इस हालिया पोस्ट द्वारा दिया गया है जो मेरे उद्घाटन पैराग्राफ में उल्लिखित प्रकार का है।

इंडेक्स

मुझे लगता है कि सबसे आसान उदाहरण मैं एक तालिका के लिए एक सूचकांक बनाने से संबंधित हो सकता था। W3schools.com पर यहाँ gumph इसे प्रदर्शन कारणों के लिए उपयोगकर्ता द्वारा अनदेखी के रूप में भी समझाने की कोशिश करता है। उनका वर्णन गैर-घोषणात्मक शिविर में एसक्यूएल सूचकांकों को लगाने के लिए लगता है और वे विशुद्ध रूप से प्रदर्शन कारणों से हाथ से जोड़ते हैं।

क्या यह मामला है कि उनका कहीं एक आदर्श एसक्यूएल डीबी है जो बाकी सभी की तुलना में बहुत अधिक घोषणात्मक है, लेकिन क्योंकि यह अच्छा है कि कोई इसके बारे में नहीं सुनता है?


@FrustratedWithFormsDesigner: मुझे पता है कि वास्तव में इसका क्या मतलब है। select whatever from sometable where FKValue in (select FKValue from sometable_2 where other_value = :param)। यह देखने के लिए तुच्छ होना चाहिए कि एक existsया एक के साथ इसे कैसे पुनर्स्थापित किया जाए join
मेसन व्हीलर

इसी तरह के तर्क का उपयोग करते हुए मुझे लगता है कि नियमित अभिव्यक्ति अभिव्यक्ति की एक अधिक घोषित पद्धति है क्योंकि मैं शायद ही कभी प्रदर्शन के सवालों के जवाब देता हूं "आपको इसे बेहतर प्रदर्शन प्राप्त करने के लिए इसे लिखना चाहिए"। मैं अपने दिमाग को मिटा रहा हूं और आधे प्रश्न को याद कर सकता हूं कि धीमी गति से रेक्सक्स में नकारात्मक लुक के पीछे या आगे के दावे के साथ क्या करना है, जहां जवाब कम समय में ही ऐसा करने के लिए अलग तरीके से regexp को फिर से लिखना था।
धान 3118

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

1
@JustinC, यह एक विस्तार से अधिक प्रतीत होता है कि प्रदर्शन उन्मुख एसक्यूएल प्रश्नों और सुझावों को कथित रूप से घोषित भाषा के लिए प्राथमिकता दी गई है?
धान 3118

एक घोषित प्रोग्रामिंग भाषा की कोई स्पष्ट परिभाषा नहीं है, और इसलिए इसके बारे में बात करना व्यर्थ है। कुछ भाषाएं अन्य की तुलना में उच्च स्तर की हैं, बस इतना ही।
गार्डेनहेड

जवाबों:


21

एसक्यूएल सैद्धांतिक रूप से घोषणात्मक है। लेकिन आप जानते हैं कि वे सिद्धांत और व्यवहार के बीच अंतर के बारे में क्या कहते हैं ...

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

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


3
कभी नहीं वास्तव में प्रभावी? SQL, LINQ, Knockout.js, Prolog, ELM भाषा। आप फिर से जांच करना चाहते हैं। मैं इस समय ज्यादातर घोषणात्मक तकनीकों का उपयोग कर रहा हूं।
brian

5
@ ब्रायन: और जब आप एक किनारे के मामले पर होते हैं, तो सभी जल्दी से पतित हो जाते हैं, जिसके बारे में किसी ने नहीं सोचा था। मुझे लगता है मुझे कहना चाहिए " सामान्य मामले में वास्तव में प्रभावी नहीं है ।"
मेसन व्हीलर

जब आपका उत्तर यह देखने के लिए तैयार होता है कि यह SQL सर्वर डेटाबेस में कैसे संग्रहीत है? :) मैं शायद ही उनमें से किसी में एक किनारे का मामला मारा जो ढांचे के भीतर हल नहीं किया जा सकता है। मैं देखता हूं कि आप कहां से आ रहे हैं, लेकिन किनारे के मामले वास्तव में मुझे इतना दर्द नहीं देते हैं कि 99% घोषित कोड के बारे में कितना फायदेमंद और आसान है। यह कहना पसंद है कि क्लोजर या एफ # खराब है क्योंकि आपको अपनी समस्या को हल करने के लिए एक परिवर्तनशील प्रकार का उपयोग करना था।
ब्रायन

11
@ ब्रायन: I rarely hit an edge case in any of them that couldn't be solved within the framework.हाँ, यह पूरा बिंदु है: फ्रेमवर्क के भीतर उन्हें हल करने का एक तरीका पता लगाना क्योंकि फ्रेमवर्क आपके लिए मूल रूप से घोषित किए गए तरीके से इसे हल करने के लिए पर्याप्त स्मार्ट नहीं है।
मेसन व्हीलर

अपडेट के लिए क्या चुनें ...? यह एक अनिवार्य आदेश लगता है।
जेस्विन जोस

6

मैं एक SQL अनुकूलन के बाद कुछ दिनों पहले यह सोच रहा था। मुझे लगता है कि हम सहमत हो सकते हैं कि एसक्यूएल विकिपीडिया की परिभाषा में एक "घोषित भाषा" है:

प्रोग्रामिंग प्रतिमान जो अपने नियंत्रण प्रवाह का वर्णन किए बिना गणना के तर्क को व्यक्त करता है

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

इस परिदृश्य में भी, कभी-कभी डेटाबेस ऑप्टिमाइज़र को सर्वश्रेष्ठ परिणाम देने के लिए उपयोगकर्ता से कुछ "संकेत" की आवश्यकता होती है।

"घोषणात्मक" भाषा की एक और आम परिभाषा है (मुझे एक आधिकारिक स्रोत नहीं मिल सकता है):

प्रोग्रामिंग प्रतिमान जो इसे प्राप्त करने के चरणों का वर्णन किए बिना गणना के वांछित परिणाम को व्यक्त करता है (यह भी कि "क्या, कैसे नहीं" का वर्णन के साथ संक्षिप्त रूप में)

यदि हम इस परिभाषा को स्वीकार करते हैं, तो हम ओपी द्वारा वर्णित मुद्दों का सामना करते हैं।

पहला मुद्दा यह है कि एसक्यूएल हमें "समान परिणाम" को परिभाषित करने के लिए कई समकक्ष तरीके देता है। संभवतः यह एक आवश्यक बुराई है: एक भाषा को जितनी अधिक अभिव्यंजक शक्ति हम देते हैं, उतनी ही एक ही चीज़ को व्यक्त करने के लिए अलग-अलग तरीके होने की संभावना है।

एक उदाहरण के रूप में, मुझे इस प्रश्न को अनुकूलित करने के लिए एक बार पूछा गया है:

 SELECT Distinct CT.cust_type,  ct.cust_type_description 
   from customer c 
              INNER JOIN 
              Customer_type CT on c.cust_type=ct.cust_type;

चूंकि प्रकार ग्राहक से बहुत कम थे और cust_typeग्राहक तालिका पर एक सूचकांक था , इसलिए मैंने इसे फिर से लिखकर एक महान सुधार प्राप्त किया है:

 SELECT CT.cust_type,  ct.cust_type_description 
   from Customer_type CT
  Where exists ( select 1 from customer c 
                  Where c.cust_type=ct.cust_type);

इस विशिष्ट मामले में, जब मैंने डेवलपर से पूछा कि वह क्या हासिल करना चाहता है, तो उसने मुझे बताया कि "मैं सभी ग्राहक प्रकार चाहता था, जिसके लिए मेरे पास कम से कम एक ग्राहक था", यह संयोग से कि कैसे ऑप्टिमाइज़र क्वेरी का वर्णन किया जा सकता है।

इसलिए, अगर मुझे एक समान और अधिक कुशल क्वेरी मिल सकती है, तो अनुकूलक ऐसा क्यों नहीं कर सकता है?

मेरा सबसे अच्छा अनुमान है कि यह दो मुख्य कारणों से है:

SQL तर्क व्यक्त करता है:

चूँकि एसक्यूएल उच्च-स्तरीय तर्क व्यक्त करता है, क्या हम वास्तव में हमें और हमारे तर्क को "आउट-मार्ट" करना चाहेंगे? मैं उत्साहपूर्वक "हाँ" चिल्लाऊंगा अगर यह सभी समय के लिए नहीं था तो मुझे आशावादी को सबसे कुशल निष्पादन पथ चुनने के लिए मजबूर करना पड़ा। मुझे लगता है कि आशावादी को अपना सर्वश्रेष्ठ (अपने तर्क को भी संशोधित करने) के लिए विचार करने की अनुमति हो सकती है, लेकिन बचाव के लिए आने के लिए हमें एक "संकेत तंत्र" दें जब कुछ पागल हो जाए (यह पहिया + ब्रेक होने जैसा होगा) एक स्वायत्त कार)।

अधिक विकल्प = अधिक समय

यहां तक ​​कि सबसे अच्छा RDBMS ऑप्टिमाइज़र सभी संभावित निष्पादन पथों का परीक्षण नहीं करता है, क्योंकि उन्हें वास्तव में तेज़ होना चाहिए: 100ms से 10ms तक किसी क्वेरी को अनुकूलित करने के लिए कितना अच्छा होगा यदि मुझे हर बार सर्वश्रेष्ठ पथ चुनने में 100ms खर्च करने की आवश्यकता है? और यह हमारे "उच्च-स्तरीय तर्क" का सम्मान करने वाले अनुकूलक के साथ है। अगर यह भी सभी समकक्ष SQL प्रश्नों का परीक्षण करना चाहिए तो अनुकूलक समय कई बार बढ़ सकता है।

क्वेरी का एक और अच्छा उदाहरण कोई RDBMS फिर से लिखना वास्तव में करने में सक्षम है ( इस दिलचस्प ब्लॉग पोस्ट से )

SELECT t1.id, t1.value, SUM(t2.value)
  FROM mytable t1
       JOIN mytable t2
         ON t2.id <= t1.id
 GROUP BY t1.id, t1.value;

की तुलना में इसे लिखा जा सकता है (आवश्यक विश्लेषणात्मक कार्य)

 SELECT id, value, SUM(t1.value) OVER (ORDER BY id)
   FROM mytable

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