क्यों "तालिका से * का चयन करें" बुरा व्यवहार माना जाता है


96

कल मैं एक "शौक" प्रोग्रामर के साथ चर्चा कर रहा था (मैं खुद एक पेशेवर प्रोग्रामर हूं)। हम उनके किसी काम में आए, और उन्होंने कहा कि वह हमेशा अपने डेटाबेस के सभी कॉलमों (यहां तक ​​कि प्रोडक्शन सर्वर / कोड में) पर सवाल उठाते हैं।

मैंने उसे ऐसा नहीं करने के लिए मनाने की कोशिश की, लेकिन वह अभी तक सफल नहीं हुआ था। मेरी राय में एक प्रोग्रामर को केवल "पूर्वाभास", दक्षता और यातायात के लिए जो आवश्यक है, उसे क्वेरी करना चाहिए। क्या मैं अपने विचार से गलत हूं?


1
मैं कहूंगा कि इसका कॉस क्या होगा अगर टेबल कंटेंट बदल जाए? कॉलम जोड़ना / निकालना आपका अभी भी चयन * .. तो आप चीजों को याद कर रहे हैं या आपकी आवश्यकता से अधिक डेटा वापस खींच रहे हैं।
JF इसे

2
@JFit इसका हिस्सा है, लेकिन पूरी कहानी से दूर।
jwenting



@gnat एक प्रश्न को वास्तव में एक बंद प्रश्न का डुप्लिकेट माना जा सकता है? (यानी क्योंकि बंद एक जगह वास्तव में उपयुक्त नहीं थी)
gbjbaanb

जवाबों:


67

इस बारे में सोचें कि आपको क्या वापस मिल रहा है, और आप अपने कोड में उन चर को कैसे बांधते हैं।

अब सोचें कि जब कोई व्यक्ति किसी कॉलम को जोड़ने (या निकालने) के लिए टेबल स्कीमा को अपडेट करता है, तब भी जब आप सीधे उपयोग नहीं कर रहे हों।

जब आप प्रश्नों को हाथ से लिख रहे हों, तब चयन * का उपयोग करना ठीक है, न कि तब जब आप कोड के लिए प्रश्न लिख रहे हों।


8
प्रदर्शन, नेटवर्क लोड, इत्यादि इत्यादि कॉलम को वापस पाने के लिए और आप जो नाम चाहते हैं, उसकी सुविधा से कहीं अधिक महत्वपूर्ण हैं।
jwenting

21
@ जेंटिंग वास्तव में? प्रदर्शन शुद्धता से अधिक मायने रखता है? वैसे भी, मैं यह नहीं देखता कि "चुनें *" केवल उन कॉलमों का चयन करने से बेहतर है जो आप चाहते हैं।
gbjbaanb

9
@ वास्तविक जीवन उत्पादन वातावरण में, आपके पास एक ही टेबल का उपयोग करके सैकड़ों अनुप्रयोग हो सकते हैं और उन सभी अनुप्रयोगों को ठीक से बनाए रखने का कोई संभव तरीका नहीं है। आप भावुकता में सही हैं, लेकिन व्यावहारिक रूप से, कॉपीराइट में काम करने की वास्तविकताओं के कारण तर्क विफल हो जाता है। एक्टिव टेबल में स्कीमा परिवर्तन हर समय होता है।
user1068

18
मुझे इस उत्तर में बात समझ में नहीं आती। यदि आप किसी तालिका में एक स्तंभ जोड़ते हैं, तो SELECT * और SELECT [कॉलम] दोनों काम करेंगे, अंतर केवल इतना है कि यदि कोड को नए कॉलम से बाँधना है, तो SELECT [Columns] को संशोधित करना होगा जबकि सेलेक्ट * नहीं होगा। यदि स्तंभ किसी तालिका से हटा दिया जाता है, तो SELECT * बाध्यकारी के बिंदु पर टूट जाएगा, जबकि क्वेरी निष्पादित होने पर SELECT [कॉलम] टूट जाएगा। यह मुझे लगता है कि SELECT * अधिक लचीला विकल्प है क्योंकि तालिका में किसी भी परिवर्तन से केवल बाइंडिंग में परिवर्तन की आवश्यकता होगी। क्या मैं कुछ भूल रहा हूँ?
तल्लुयुय

11
@ जीबीजबांब फिर नाम से कॉलम एक्सेस करें। जब तक आप क्वेरी में स्तंभ क्रम निर्दिष्ट नहीं करते तब तक कुछ और स्पष्ट रूप से बेवकूफ होगा।
इमीबिस

179

स्कीमा परिवर्तन

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

किसी भी तरह से, एक स्कीमा परिवर्तन डेटा के निष्कर्षण के साथ समस्याएं पैदा कर सकता है।

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

डेटा ओवरहेड

कुछ स्तंभों में उनके साथ जुड़ी महत्वपूर्ण मात्रा में डेटा हो सकता है। वापस चयन करने *से सारा डेटा खिंच जाएगा । हाँ, यहाँ है कि varchar(4096)1000 पंक्तियों पर thats कि तुम वापस चुना है आप डेटा की एक अतिरिक्त संभव 4 मेगाबाइट है कि आप की जरूरत नहीं दे रहे हैं, लेकिन तार वैसे भी भेजा जाता है।

स्कीमा परिवर्तन से संबंधित है, कि जब आप पहली बार तालिका बनाते हैं, तो यह वहां मौजूद नहीं हो सकता है, लेकिन अब वहां है।

आशय व्यक्त करने में विफलता

जब आप वापस चुनते हैं *और 20 कॉलम प्राप्त करते हैं, लेकिन उनमें से केवल 2 की आवश्यकता होती है, तो आप कोड का इरादा नहीं बता रहे हैं। जब कोई ऐसा प्रश्न देखता है select *जो यह नहीं जानता है कि इसके महत्वपूर्ण भाग क्या हैं। क्या मैं इन स्तंभों को शामिल करके इसे तेज़ी से बनाने के बजाय इस अन्य योजना का उपयोग करने के लिए क्वेरी बदल सकता हूं? मुझे नहीं पता क्योंकि क्वेरी रिटर्न का इरादा स्पष्ट नहीं है।


कुछ SQL फ़िडल्स पर नज़र डालते हैं जो उन स्कीमा का पता लगाते हैं जो थोड़ा और बदल जाते हैं।

सबसे पहले, प्रारंभिक डेटाबेस: http://sqlfiddle.com/#/2/a67dd/1

DDL:

create table one (oneid int, data int, twoid int);
create table two (twoid int, other int);

insert into one values (1, 42, 2);
insert into two values (2, 43);

एसक्यूएल:

select * from one join two on (one.twoid = two.twoid);

और कॉलम आप वापस पाने के हैं oneid=1, data=42, twoid=2, और other=43

अब, यदि मैं तालिका एक में एक स्तंभ जोड़ दूं तो क्या होगा? http://sqlfiddle.com/#!2/cd0b0/1

alter table one add column other text;

update one set other = 'foo';

और एक ही क्वेरी से अपने परिणाम के रूप में पहले कर रहे हैं oneid=1, data=42, twoid=2, और other=foo

तालिकाओं में से एक में परिवर्तन एक के मानों को बाधित करता है select *और अचानक एक अन्य के लिए 'अन्य' के अपने बंधन को एक त्रुटि फेंकने वाला है और आपको पता नहीं क्यों।

अगर इसके बजाय आपका SQL स्टेटमेंट था

select 
    one.oneid, one.data, two.twoid, two.other
from one join two on (one.twoid = two.twoid);

तालिका एक में परिवर्तन से आपका डेटा बाधित नहीं होगा। वह क्वेरी परिवर्तन से पहले और परिवर्तन के बाद भी चलती है।


इंडेक्सिंग

जब आप करते हैं तो select * fromआप सभी पंक्तियों को खींच रहे होते हैं जो सभी तालिकाओं को बनाते हैं जो स्थितियों से मेल खाते हैं। यहां तक ​​कि तालिकाओं के बारे में आप वास्तव में परवाह नहीं करते हैं। जबकि इसका मतलब है कि अधिक डेटा स्थानांतरित हो गया है, स्टैक के नीचे एक और प्रदर्शन समस्या है जो आगे झुक रही है।

इंडेक्स। (SO पर संबंधित: चुनिंदा स्टेटमेंट में इंडेक्स का उपयोग कैसे करें? )

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

यदि आप केवल एक उपयोगकर्ता का अंतिम नाम, कहते हैं, का चयन कर रहे हैं (जो आप बहुत कुछ करते हैं और इस पर एक सूचकांक है), डेटाबेस केवल एक सूचकांक स्कैन कर सकता है ( केवल विकि स्कैन सूचकांक को स्कैन करता है , mysql पूर्ण तालिका स्कैन बनाम पूर्ण इंडेक्स स्कैन , इंडेक्स-ओनली स्कैन: टेबल एक्सेस से बचना )।

यदि संभव हो तो केवल अनुक्रमित से पढ़ने के बारे में काफी अनुकूलन है। जानकारी को प्रत्येक अनुक्रमणिका पृष्ठ पर तेजी से खींचा जा सकता है क्योंकि आप इसे भी कम खींच रहे हैं - आप उन सभी अन्य स्तंभों में नहीं खींच रहे हैं select *। सूचकांक के लिए यह संभव है कि केवल 100x तेज़ी के क्रम पर परिणाम वापस करने के लिए स्कैन करें (स्रोत: चुनें * खराब है )।

यह नहीं कह रहा है कि एक पूर्ण सूचकांक स्कैन महान है, यह अभी भी एक पूर्ण स्कैन है - लेकिन यह एक पूर्ण तालिका स्कैन से बेहतर है। एक बार जब आप उन सभी तरीकों का पीछा करना शुरू कर देते हैं जो select *प्रदर्शन को नुकसान पहुंचाते हैं तो आप नए खोजते रहते हैं।

संबंधित पढ़ना


2
@ पहले मैं सहमत था - लेकिन जब मैंने उत्तर दिया (प्रथम) तो मैंने कभी नहीं सोचा था कि यह प्रश्न काफी चर्चा और टिप्पणी पैदा करेगा! यह केवल नाम वाले कॉलम के लिए क्वेरी करने के लिए स्पष्ट है, है ना ?!
gbjbaanb

3
कॉलम जोड़कर सब कुछ तोड़ना भी एक अच्छा कारण है कि कोड को हमेशा एक कोडर में कॉलम को हार्ड-कोडेड ऑर्डिनल के नाम से नहीं एक्सेस करना चाहिए ...
जूलिया हेवर्ड

1
@gbjbaanb यह मेरे लिए है। लेकिन बहुत से लोग औपचारिक पृष्ठभूमि / प्रशिक्षण के बिना SQL क्वेरी लिखने के लिए आते हैं। उनके लिए यह स्पष्ट नहीं हो सकता है।
टन

1
@Aaronaught मैंने इसे इंडेक्सिंग मुद्दों पर अतिरिक्त बिट के साथ अद्यतन किया है। क्या कोई अन्य बिंदु हैं जो मुझे गलत के लिए लाना चाहिए select *?

3
वाह, स्वीकृत जवाब वास्तव में इतना खराब था कि मैं किसी भी चीज की व्याख्या कर रहा था, मैंने उसे वोट दिया। आश्चर्य हुआ कि यह स्वीकृत उत्तर नहीं है। +1।
बेन ली

38

एक और चिंता: यदि यह एक JOINक्वेरी है और आप क्वेरी परिणाम को एक सहयोगी सरणी (जैसा कि PHP में मामला हो सकता है) में प्राप्त कर रहे हैं, तो यह बग-प्रवण है।

बात यह है कि

  1. यदि तालिका fooमें कॉलम idऔर हैंname
  2. यदि तालिका barमें कॉलम हैं idऔर address,
  3. और आपके कोड में आप उपयोग कर रहे हैं SELECT * FROM foo JOIN bar ON foo.id = bar.id

लगता है कि क्या होता है जब किसी एक कॉलम जोड़ने पर nameकरने के लिए barतालिका।

कोड अचानक, क्योंकि अब ठीक से काम करना बंद कर देगा nameस्तंभ परिणामों में दिखाई देता दो बार और यदि आप एक सरणी में परिणाम भंडारण कर रहे हैं, दूसरी से डेटा name( bar.name) पहले के ऊपर लिख देगा name( foo.name)!

यह बहुत बुरा बग है क्योंकि यह बहुत गैर-स्पष्ट है। यह पता लगाने में थोड़ा समय लग सकता है, और ऐसा कोई तरीका नहीं है कि व्यक्ति किसी अन्य स्तंभ को तालिका में जोड़कर इस तरह के अवांछनीय दुष्प्रभाव का अनुमान लगा सके।

(सच्ची कहानी)।

इसलिए, उपयोग न करें *, आप जो कॉलम पुनर्प्राप्त कर रहे हैं और जहां उपयुक्त हो वहां उपनाम का उपयोग करें।


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

4
सिद्धांत रूप में, लेकिन यदि आप सुविधा के लिए वाइल्डकार्ड का उपयोग करते हैं, तो आप इस पर भरोसा करते हैं कि स्वचालित रूप से आपको अस्तित्व में सभी कॉलम दिए जा सकते हैं और तालिकाएँ बढ़ने पर कभी भी क्वेरी को अपडेट करने की जहमत नहीं उठानी चाहिए। यदि आप प्रत्येक कॉलम को निर्दिष्ट कर रहे हैं, तो आपको अपने SELECTक्लॉज़ में एक और जोड़ने के लिए क्वेरी पर जाने के लिए मजबूर किया जाता है और यह तब होता है जब आप उम्मीद करते हैं कि नाम अद्वितीय नहीं है। BTW मुझे नहीं लगता कि बड़े डेटाबेस वाले सिस्टम में यह बहुत दुर्लभ है। जैसा कि मैंने कहा, मैंने एक बार PHP कोड के एक बड़े मडबॉल में इस बग का शिकार करने में कुछ घंटे बिताए। और मुझे अभी एक और मामला मिला: stackoverflow.com/q/17715049/168719
कोनराड मोरावस्की

3
मैं पिछले हफ्ते एक घंटा बिताता हूं ताकि सलाहकार सलाहकारों के माध्यम से इसे प्राप्त कर सकूं। उन्होंने कहा कि एक एसक्यूएल गुरु माना जाता है ... साई ...
Tonny

22

हर कॉलम को छोड़ना कई मामलों में पूरी तरह वैध हो सकता है।

हमेशा हर कॉलम को क्वेरी करना नहीं है।

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

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

यह आपके एप्लिकेशन के लिए अधिक काम करता है, इस अतिरिक्त डेटा को वापस खींचने और संग्रहीत करने के लिए, जो कि संभवतः इसकी परवाह नहीं करता है।

आप उनके क्रम को बदलने वाले स्तंभों के जोखिम को चलाते हैं। ठीक है, आप इस बारे में चिंता करने की ज़रूरत नहीं होना चाहिए (और आप नहीं होगा अगर आप उन्हें एक बार में मिल जाने के लिए और किसी को [बाकी] तालिका में स्तंभ क्रम को पुनर्व्यवस्थित करने का फैसला करता है, तो आप केवल कॉलम आप की जरूरत का चयन करें) लेकिन, , कि सावधानीपूर्वक तैयार की गई, CSV निर्यात जिसे आप हॉल के नीचे खातों को देते हैं अचानक सभी पॉट में चला जाता है - फिर से, बिना किसी स्पष्ट कारण के।

BTW, मैंने कहा है "किसी और []" एक दो बार, ऊपर। याद रखें कि डेटाबेस स्वाभाविक रूप से बहु-उपयोगकर्ता हैं; आप उन पर नियंत्रण नहीं रख सकते हैं जो आपको लगता है कि आप करते हैं।


3
मुझे लगता है कि स्कीमा-अज्ञेय तालिका देखने की सुविधाओं जैसी चीजों के लिए हमेशा हर कॉलम को क्वेरी करना वैध हो सकता है। बहुत सामान्य स्थिति नहीं है, लेकिन आंतरिक-उपयोग-केवल उपकरण के संदर्भ में ऐसी चीजें उपयोगी हो सकती हैं।
सुपरकैट

1
@ supercat यह केवल एक "SELECT *" के लिए केवल मान्य उपयोग-केस के बारे में है, जिसके बारे में मैं सोच सकता हूं। और फिर भी मैं क्वेरी को "सेलेक्ट टॉप 10 *" (एमएस एसक्यूएल में) या "लिमिट 10" (माइएसक्यूएल) में जोड़ना पसंद करूंगा या "व्हाट राउम <= 10" (ओरेकल) जोड़ना पसंद करूंगा। आमतौर पर उस मामले में यह "पूर्ण सामग्री की तुलना में" क्या कॉलम हैं और कुछ नमूना डेटा हैं "के बारे में अधिक है।
Tonny

@ टोन: SQL सर्वर ने TOPसीमा जोड़ने के लिए अपनी डिफ़ॉल्ट स्क्रिप्ट को बदल दिया ; मुझे यकीन नहीं है कि कोड कितना महत्वपूर्ण है अगर यह उतना ही पढ़ता है जितना कि यह प्रदर्शित करता है और फिर क्वेरी का निपटान करता है। मुझे लगता है कि क्वेरी प्रतिक्रियाओं को कुछ आलसी तरीके से संसाधित किया जाता है, हालांकि मुझे विवरण नहीं पता है। किसी भी मामले में, मुझे लगता है कि यह कहने के बजाय "वैध नहीं है", यह कहना बेहतर होगा "... बहुत कम में वैध है "; मूल रूप से, मैं उन वैध मामलों को संक्षेप में बताऊंगा जहां उपयोगकर्ता को एक बेहतर विचार होगा कि प्रोग्रामर की तुलना में क्या सार्थक है।
सुपरकैट

@ सुपरकार मैं इससे सहमत हो सकता हूं। और मैं वास्तव में जिस तरह से आप इसे अपने अंतिम वाक्य में डालते हैं। मुझे उस एक को याद करना है।
Tonny

11

संक्षिप्त उत्तर है: यह इस बात पर निर्भर करता है कि वे किस डेटाबेस का उपयोग करते हैं। रिलेशनल डेटाबेस को आपके द्वारा आवश्यक डेटा को तेज, विश्वसनीय और परमाणु तरीके से निकालने के लिए अनुकूलित किया जाता है। बड़े डेटासेट और जटिल प्रश्नों पर, यह चयन * की तुलना में बहुत तेज़ और संभावित रूप से सुरक्षित है और 'कोड' की तरफ जुड़ने के बराबर है। की-वैल्यू स्टोर्स में ऐसी कार्यक्षमताएँ लागू नहीं हो सकती हैं, या उत्पादन में उपयोग करने के लिए पर्याप्त परिपक्व नहीं हो सकती हैं।

उस ने कहा, आप अभी भी चुन सकते हैं कि जो डेटा संरचना आप SELECT * के साथ उपयोग कर रहे हैं और बाकी कोड में काम करें लेकिन यदि आप स्केल करना चाहते हैं तो आपको प्रदर्शन में अड़चनें आएंगी।

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

बेशक, यह एक प्रोग्रामर में निवेश करने की तुलना में रैम और सीपीयू को जोड़ना सस्ता है जो कि एसक्यूएल क्वेश्चन कर सकता है और यहां तक ​​कि एक JOIN क्या है इसकी अस्पष्ट समझ भी है।


SQL सीखें! यह इतना कठिन नहीं है। यह डेटाबेस की "मूल" भाषा दूर-दूर तक है। यह शक्तिशाली है। यह सुरुचिपूर्ण है। यह समय की कसौटी पर खरा उतरा है। और कोई भी तरीका नहीं है कि आप "कोड" साइड पर एक ज्वाइन लिखने जा रहे हैं जो डेटाबेस में शामिल होने से ज्यादा कुशल है, जब तक कि आप एसक्यूएल जॉइन करने में वास्तव में अयोग्य न हों। इस बात पर विचार करें कि "कोड जॉइन" करने के लिए, आपको एक साधारण 2-टेबल जॉइन में भी दोनों डेटा को सभी टेबल से खींचना होगा। या क्या आप अनुक्रमणिका आँकड़े खींच रहे हैं और उन का उपयोग करके यह तय करते हैं कि आपके शामिल होने से पहले किस तालिका डेटा को खींचना है? ऐसा नहीं सोचा था ... डेटाबेस का सही तरीके से उपयोग करना सीखें, लोग।
क्रेग

@ क्रेग: रिलेशनल डेटाबेस में एसक्यूएल दूर-दूर तक आम है । यह एकमात्र प्रकार के DB से बहुत दूर है, हालांकि ... और एक कारण है कि अधिक आधुनिक डेटाबेस दृष्टिकोण को अक्सर NoSQL कहा जाता है। : पी कोई नहीं जानता कि मैं विडंबना की भारी खुराक के बिना एसक्यूएल को "सुरुचिपूर्ण" कहूंगा। यह सिर्फ कई विकल्पों से कम बेकार है, जहां तक ​​संबंधपरक डेटाबेस का संबंध है।
cHao

@ cHao मुझे दशकों से विभिन्न प्रकार के डेटाबेस के बारे में पता है । "Nosql" डेटाबेस पिक हमेशा के लिए रहा है। "NoSQL" दूरस्थ रूप से एक नई अवधारणा भी नहीं है। ORM भी हमेशा के लिए चारों ओर हो गया है, और वे हमेशा धीमा रहा है। धीमहि! = अच्छा है। लालित्य के लिए (LINQ?) के रूप में, आप मुझे समझा नहीं सकते कि यह कहां या कहां के लिए उचित या सुरुचिपूर्ण है: पृष्ठ 2 पर अपराध करने का समयCustomer customer = this._db.Customers.Where( “it.ID = @ID”, new ObjectParameter( “ID”, id ) ).First(); देखें ।
Craig

@ क्रेग: मुझे ओआरएम पर भी शुरू न करें। लगभग हर प्रणाली बाहर यह बुरी तरह से करता है, और अमूर्त जगह पर लीक हो जाता है। ऐसा इसलिए है क्योंकि रिलेशनल डीबी रिकॉर्ड्स ऑब्जेक्ट नहीं हैं - सबसे अच्छे रूप में, वे एक वस्तु के हिस्से के क्रमबद्ध हिम्मत हैं। लेकिन LINQ के लिए, आप वास्तव में वहाँ जाना चाहते हैं? SQLish समतुल्य कुछ ऐसा है var cmd = db.CreateCommand(); cmd.CommandText = "SELECT TOP 1 * FROM Customers WHERE ID = @ID"; cmd.Parameters.AddWithValue("@ID", id); var result = cmd.ExecuteReader();.... और फिर प्रत्येक पंक्ति से एक ग्राहक बनाने के लिए आगे बढ़ें। LINQ पैंट कि बंद धड़कता है।
19

@ क्रेग: दी, यह उतना सुंदर नहीं है जितना यह हो सकता है। लेकिन यह कभी भी उतना सुंदर नहीं होगा, जितना कि मैं चाहूंगा कि यह SQL में .net कोड को रूपांतरित कर सकता है। :) आप किस बिंदु पर कह सकते हैं var customer = _db.Customers.Where(it => it.id == id).First();
cHao

8

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

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


3
यह शायद यहाँ सबसे महत्वपूर्ण कारणों में से एक है, और इसे वोटों का बस थोड़ा सा हिस्सा मिला है। के साथ कूड़े एक कोडबेस की स्थिरता select *बहुत बदतर है!
ईमोन नेरबोन

6

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

कुछ DB ऑप्टिमाइज़ेशन गैर-निश्चित लंबाई के रिकॉर्ड को एक अलग फ़ाइल में निर्धारित लंबाई के हिस्सों तक पहुंच को तेज करने के लिए भी चुन सकते हैं, उस के उद्देश्य का चयन करते हुए * पराजित करता है


1

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


3
सहमत हूँ, हालांकि मैं किसी भी मामले में कॉलम नाम द्वारा निर्धारित परिणाम से मूल्यों को बाहर निकालने की सलाह दूंगा।
रोरी हंटर

दूसरा, किया हुआ। कॉलम नामों का उपयोग करें, कॉलम ऑर्डर पर निर्भर न हों। स्तंभ क्रम एक भंगुर निर्भरता है। नाम कुछ वास्तविक डिज़ाइन प्रयास से प्राप्त होने चाहिए (आप आशा करते हैं), या आप अपने प्रश्न में स्पष्ट रूप से उपनाम वाले कॉलम या संगणना या परस्पर विरोधी स्तंभ नाम, और आपके द्वारा निर्दिष्ट स्पष्ट उपनाम का संदर्भ लें। लेकिन आदेश पर भरोसा बहुत ज्यादा डक्ट टेप और प्रार्थना है ...
क्रेग

1

मुझे ऐसा कोई कारण नहीं दिख रहा है जिसके निर्माण के लिए आप इसका उपयोग न करें - डेटाबेस से सभी कॉलम पुनः प्राप्त करें। मैं तीन मामले देखता हूं:

  1. डेटाबेस में एक कॉलम जोड़ा जाता है और आप इसे कोड में भी चाहते हैं। a) एक उचित संदेश के साथ * असफल हो जाएगा। बी) बिना * काम करेगा, लेकिन वह नहीं करेगा जो आप उम्मीद करते हैं जो बहुत बुरा है।

  2. डेटाबेस में एक कॉलम जोड़ा जाता है और आप इसे कोड में नहीं चाहते हैं। क) के साथ * विफल हो जाएगा; इसका मतलब यह है कि * अब लागू नहीं होता है क्योंकि यह शब्दार्थ "सभी को पुनः प्राप्त करने" का अर्थ है। b) बिना * काम करेगा।

  3. एक कॉलम हटा दिया गया है कोड किसी भी तरह से विफल हो जाएगा।

अब सबसे आम मामला 1 मामला है (जब से आपने इस्तेमाल किया है * जिसका अर्थ है कि आप सबसे अधिक शायद सभी चाहते हैं); बिना * आपके पास वह कोड हो सकता है जो ठीक काम करता है, लेकिन वह नहीं करता है जो अपेक्षित है, वह बहुत ही बुरा कोड है जो एक उचित त्रुटि संदेश के साथ विफल हो जाता है

मैं उस कोड को ध्यान में नहीं रख रहा हूं जो कॉलम इंडेक्स के आधार पर कॉलम डेटा को पुनर्प्राप्त करता है जो मेरी राय में त्रुटि-प्रवण है। स्तंभ नाम के आधार पर इसे पुनर्प्राप्त करना बहुत अधिक तर्क है।


आपका आधार गलत है। Select *विज्ञापन विकास उद्देश्यों के लिए नहीं, बल्कि तदर्थ क्वेरी के लिए एक सुविधा के रूप में अधिक इरादा था। या सांख्यिकीय निर्माण में उपयोग के लिए जैसे select count(*)कि क्वेरी इंजन यह तय करने की अनुमति देता है कि क्या सूचकांक का उपयोग किया जाए, किस सूचकांक का उपयोग करना है और इसी तरह और आप कोई वास्तविक कॉलम डेटा वापस नहीं कर रहे हैं। या जैसे खंडों में उपयोग के लिए where exists( select * from other_table where ... ), जो फिर से क्वेरी इंजन को अपने दम पर सबसे कुशल मार्ग चुनने के लिए एक आमंत्रण है और उपकुंजी का उपयोग केवल मुख्य क्वेरी से परिणाम को बाधित करने के लिए किया जाता है। आदि
क्रेग

@ क्रेग का मानना ​​है कि एसक्यूएल पर प्रत्येक पुस्तक / ट्यूटोरियल कहता है कि select *सभी स्तंभों को प्राप्त करने का शब्दार्थ है; यदि आपके आवेदन को वास्तव में इसकी आवश्यकता है, तो मुझे इसका उपयोग न करने का कोई कारण नहीं दिखता है। क्या आप कुछ संदर्भ (ओरेकल, आईबीएम, माइक्रोसॉफ्ट आदि) को इंगित कर सकते हैं जो उस उद्देश्य का उल्लेख करते हैं जिसका select *निर्माण सभी स्तंभों को पुनः प्राप्त नहीं करना था?
m3th0dman

खैर, निश्चित रूप select *से सभी स्तंभों को पुनः प्राप्त करने के लिए मौजूद है ... एक सुविधा सुविधा के रूप में, तदर्थ क्वेरी के लिए, इसलिए नहीं कि यह उत्पादन सॉफ्टवेयर में एक महान विचार है। इस पृष्ठ पर उत्तरों में कारण पहले से ही बहुत अच्छे से कवर किए गए हैं, यही वजह है कि मैंने अपना विस्तृत उत्तर नहीं बनाया: •) प्रदर्शन समस्याएँ, नेटवर्क पर बार-बार डेटा का उपयोग करना जो आप कभी उपयोग नहीं करते हैं, •) कॉलम एलियासिंग के साथ समस्याएँ, •) क्वेरी प्लान ऑप्टिमाइज़ेशन विफलताओं (कुछ मामलों में अनुक्रमित का उपयोग करने में विफलता), •) अक्षम सर्वर I / O उन मामलों में जहां सीमित चयन पूरी तरह से अनुक्रमित इत्यादि का उपयोग कर सकते थे ,
क्रेग

हो सकता है कि यहां एक किनारे का मामला है या select *जो वास्तविक उत्पादन एप्लिकेशन के उपयोग को सही ठहराता है , लेकिन एक किनारे के मामले की प्रकृति यह है कि यह सामान्य मामला नहीं है। :-)
क्रेग

@ क्रैग कारण डेटाबेस से सभी कॉलमों का उपयोग न करने के खिलाफ है select *; अगर मैं वास्तव में आपको सभी कॉलमों की आवश्यकता हो तो मैं कह रहा था कि मुझे कोई कारण नहीं है कि आपको इसका उपयोग क्यों नहीं करना चाहिए select *; हालांकि कुछ ऐसे परिदृश्य होने चाहिए जहां सभी स्तंभों की आवश्यकता होती है।
m3th0dman

1

इसे इस तरह से सोचें ... यदि आप किसी तालिका से सभी स्तंभों को क्वेरी करते हैं जिसमें कुछ छोटे स्ट्रिंग या संख्यात्मक फ़ील्ड हैं, तो कुल 100k डेटा है। बुरा अभ्यास, लेकिन यह प्रदर्शन करेगा। अब एक एकल फ़ील्ड जोड़ें, जो कहता है, एक छवि या 10mb शब्द दस्तावेज़। अब आपकी तेजी से प्रदर्शन कर रही क्वेरी तुरंत और रहस्यमय तरीके से खराब प्रदर्शन करने लगती है, सिर्फ इसलिए कि एक फ़ील्ड को तालिका में जोड़ा गया था ... आपको उस विशाल डेटा तत्व की आवश्यकता नहीं हो सकती है, लेकिन क्योंकि आपने ऐसा किया Select * from Tableहै।


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