A = 0 और b = 0 और… z = 0 बनाम a + b + c + d = 0 का प्रदर्शन


20

यह एक सरल प्रश्न है जिसका उत्तर मुझे नहीं मिल रहा है।

प्रदर्शन के संदर्भ में, यदि मेरे पास कोई WHEREखंड है जैसे कि a=0 and b=0 and ... z=0, क्या मैं उस स्थिति को बदलने के साथ कोई प्रदर्शन प्राप्त करूंगा a+b+...+z=0?

दूसरे शब्दों में, क्या निम्नलिखित की जगह कोई प्रदर्शन लाभ है

Select * 
From MyTable 
Where A=0 and B=0 and C=0 and D=0...

साथ में

Select * 
From MyTable 
Where A+B+C+D=0...

मुझे पता है कि यह इंडेक्स पर निर्भर कर सकता है, लेकिन इस उद्देश्य के लिए, मान लें कि कोई इंडेक्स मौजूद नहीं है। क्या अंकगणित ऑपरेटर (+) "OR" या "AND" लॉजिकल ऑपरेटर से बेहतर प्रदर्शन करता है?

मैं इस धारणा के तहत हूं कि यह अतिरिक्त ANDs या ORs के साथ कई स्थितियों से बेहतर प्रदर्शन करता है।

परीक्षण के परिणाम

4.2 मिलियन पंक्तियों की तालिका पर

पंक्तियाँ लौटाना जहाँ A = 0 B = 0 और C = 0 -> 351748 पंक्तियाँ

इसके अलावा (A + B + C = 0) में 5 सेकंड का समय लगा जबकि लॉजिकल कंडीशंस A = 0 और B = 0 और C = 0 में 11 सेकंड का समय था।

दूसरी ओर

पंक्तियाँ लौटाना जहाँ A <> 0 B <> 0 या C <> 0 -> 3829750 पंक्तियाँ 58 सेकंड

पंक्तियाँ वापस करना जहाँ F65 + F67 + f64 <> 0 -> 3829750 पंक्तियाँ 57 सेकंड

OR के लिए, ऐसा लगता है कि कोई महत्वपूर्ण अंतर नहीं है।

मैं gbn से सहमत हूं:

यदि A -1 है और B 1 है, A + B = 0 है, लेकिन A = 0 और B = 0 गलत है

और AMtwo के साथ:

एबीएस (ए) + एबीएस (बी) + एबीएस (सी) + एबीएस (डी) ... भले ही आप केवल सकारात्मक मूल्यों की उम्मीद करते हैं, यदि स्तंभ नकारात्मक मूल्यों को स्वीकार करता है, तो आपको यह मान लेना चाहिए कि आपका सामना हो सकता है।

परिणाम बहुत प्रभावशाली हैं, जैसा कि मैंने सोचा था, ऐसा लगता है कि इसके अलावा तार्किक ऑपरेटरों की तुलना में बहुत तेज है।

ए = फ्लोट, बी = मनी और सी = फ्लोट। उपयोग की गई क्वेरी को दिखाया गया है। मेरे मामले में, सभी सकारात्मक संख्या हैं। कोई सूचकांक नहीं। यह मेरे दिमाग में बस तर्कसंगत है कि इसके अलावा तार्किक परिस्थितियों की तुलना में जल्दी होगा!


क्या ये बूलियन हैं? आप 4 (उदाहरणों में), या 26 (शीर्षक में) के बारे में कितने कॉलम में बात कर रहे हैं? इससे फर्क पड़ता है। SQL सर्वर का क्या संस्करण? फ़्लोट और पैसा खेलने में कहाँ आता है? हम कितनी पंक्तियाँ मान रहे हैं? इस सवाल के एक टन कारक हैं।
इवान कैरोल

@ इवान कैरोल वे बुलियन नहीं हैं, वे गैर-अनुक्रमित संख्या (इंट, फ्लोट, मनी, आदि) हैं। SQL संस्करण (SQL2012 और ऊपर) के बावजूद, पंक्तियों या स्तंभों की संख्या, सवाल यह पता लगाना था कि कौन सा ऑपरेटर बेहतर - तार्किक बनाम अंकगणितीय ऑपरेटरों का प्रदर्शन करता है। जैसा कि आप देख सकते हैं कि मैक्स वर्नोन अपने उदाहरणों के साथ सिद्धांत को पूरी तरह से प्रदर्शित करता है।
जॉन

जवाबों:


46

अपने प्रश्न में, आप कुछ परीक्षण जो आपने तैयार किए हैं, जहां आप "साबित" करते हैं कि अतिरिक्त विकल्प असतत कॉलम की तुलना में तेज है। मुझे संदेह है कि आपकी परीक्षा पद्धति कई मायनों में त्रुटिपूर्ण हो सकती है, क्योंकि @gbn और @srutzky ने अपना रुख किया है।

सबसे पहले, आपको यह सुनिश्चित करने की आवश्यकता है कि आप SQL सर्वर प्रबंधन स्टूडियो (या जो भी क्लाइंट आप उपयोग कर रहे हैं) का परीक्षण नहीं कर रहे हैं। उदाहरण के लिए, यदि आप SELECT *3 मिलियन पंक्तियों वाली तालिका से चल रहे हैं, तो आप SSMS की SQL सर्वर से पंक्तियों को खींचने और उन्हें स्क्रीन पर प्रस्तुत करने की क्षमता का परीक्षण कर रहे हैं। आप कुछ का उपयोग करने के लिए बहुत बेहतर हैं जैसे SELECT COUNT(1)कि नेटवर्क पर लाखों पंक्तियों को खींचने की आवश्यकता है, और उन्हें स्क्रीन पर प्रस्तुत करना।

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

शीत-कैश परीक्षण के लिए, आपको चलाने की आवश्यकता है CHECKPOINT और DBCC DROPCLEANBUFFERSपरीक्षण के प्रत्येक रन से पहले।

आपके प्रश्न के बारे में पूछे जाने वाले परीक्षण के लिए, मैंने निम्नलिखित परीक्षण-बिस्तर बनाया:

IF COALESCE(OBJECT_ID('tempdb..#SomeTest'), 0) <> 0
BEGIN
    DROP TABLE #SomeTest;
END
CREATE TABLE #SomeTest
(
    TestID INT NOT NULL
        PRIMARY KEY 
        IDENTITY(1,1)
    , A INT NOT NULL
    , B FLOAT NOT NULL
    , C MONEY NOT NULL
    , D BIGINT NOT NULL
);

INSERT INTO #SomeTest (A, B, C, D)
SELECT o1.object_id, o2.object_id, o3.object_id, o4.object_id
FROM sys.objects o1
    , sys.objects o2
    , sys.objects o3
    , sys.objects o4;

SELECT COUNT(1) 
FROM #SomeTest;

यह मेरी मशीन पर 260,144,641 की गिनती देता है।

"जोड़" विधि का परीक्षण करने के लिए, मैं चलाता हूं:

CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;

SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE (st.A + st.B + st.C + st.D) = 0;
GO
SET STATISTICS IO, TIME OFF;

संदेश टैब दिखाता है:

टेबल '#SomeTest'। स्कैन काउंट 3, लॉजिकल रीड 1322661, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड 1313877, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लोब रीड-फॉरवर्ड रीड्स 0।

SQL सर्वर निष्पादन समय: CPU समय = 49047 एमएस, बीता समय = 173451 एमएस।

"असतत कॉलम" परीक्षण के लिए:

CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;

SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE st.A = 0
    AND st.B = 0
    AND st.C = 0
    AND st.D = 0;
GO

SET STATISTICS IO, TIME OFF;

संदेश टैब से फिर:

टेबल '#SomeTest'। स्कैन काउंट 3, लॉजिकल रीड 1322661, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड 1322661, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लोब रीड-फॉरवर्ड रीड्स 0।

SQL सर्वर निष्पादन समय: CPU समय = 8938 एमएस, बीता समय = 162581 एमएस।

ऊपर दिए गए आंकड़ों से आप दूसरे संस्करण को देख सकते हैं, 0 की तुलना में असतत कॉलम के साथ, बीता हुआ समय लगभग 10 सेकंड कम है, और सीपीयू का समय लगभग 6 गुना कम है। ऊपर दिए गए मेरे परीक्षणों में लंबी अवधि अधिकतर डिस्क से बहुत सी पंक्तियाँ पढ़ने का परिणाम है। यदि आप पंक्तियों की संख्या को 3 मिलियन तक गिरा देते हैं, तो आप देखते हैं कि अनुपात लगभग एक ही है, लेकिन बीता हुआ समय ध्यान देने योग्य है, क्योंकि डिस्क I / O का प्रभाव बहुत कम है।

"अतिरिक्त" विधि के साथ:

टेबल '#SomeTest'। स्कैन काउंट 3, लॉजिकल रीड्स 15255, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लॉब रीड-फॉरवर्ड रीड्स 0।

SQL सर्वर निष्पादन समय: CPU समय = 499 ms, बीता समय = 256 ms।

"असतत कॉलम" विधि के साथ:

टेबल '#SomeTest'। स्कैन काउंट 3, लॉजिकल रीड्स 15255, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लॉब रीड-फॉरवर्ड रीड्स 0।

SQL सर्वर निष्पादन समय: CPU समय = 94 एमएस, बीता हुआ समय = 53 एमएस।

इस परीक्षण के लिए वास्तव में बहुत बड़ा अंतर क्या होगा? एक उपयुक्त सूचकांक, जैसे:

CREATE INDEX IX_SomeTest ON #SomeTest(A, B, C, D);

"जोड़" विधि:

टेबल '#SomeTest'। स्कैन काउंट 3, लॉजिकल 14235 पढ़ता है, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लॉब रीड-फॉरवर्ड रीड्स 0।

SQL सर्वर निष्पादन समय: CPU समय = 546 ms, बीता समय = 314 ms।

"असतत कॉलम" विधि:

टेबल '#SomeTest'। स्कैन काउंट 1, लॉजिकल रीड 3, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लॉब लॉजिकल रीड्स 0, लॉब फिजिकल रीड्स 0, लॉब रीड-फॉरवर्ड रीड्स 0।

SQL सर्वर निष्पादन समय: CPU समय = 0 ms, बीता समय = 0 ms।

प्रत्येक क्वेरी के लिए निष्पादन योजना (उपरोक्त सूचकांक के साथ जगह में) काफी बता रही है।

"जोड़" विधि, जिसे पूरे सूचकांक का स्कैन करना चाहिए:

यहां छवि विवरण दर्ज करें

और "असतत कॉलम" विधि, जो सूचकांक की पहली पंक्ति की ओर ले जा सकती है, जहां प्रमुख सूचकांक कॉलम Aशून्य है:

यहां छवि विवरण दर्ज करें


24

मान लीजिए कि आपके पास A, B, C और D पर एक इंडेक्स है, जिसे फ़िल्टर भी किया जा सकता है।

इसके बाद सूचकांक का उपयोग करने की अधिक संभावना है।

Where A=0 and B=0 and C=0 and D=0

अन्य समाचारों में, यदि A -1 है और B 1 है, A+B=0सत्य है लेकिन A=0 and B=0असत्य है।


7

(कृपया ध्यान दें कि यह उत्तर प्रश्न में उल्लिखित किसी भी परीक्षण से पहले प्रस्तुत किया गया था: प्रश्न का पाठ परीक्षा परिणाम अनुभाग के ठीक ऊपर समाप्त हुआ था ।)

मुझे लगता है कि अलग-अलग ANDपरिस्थितियों को प्राथमिकता दी जाएगी क्योंकि ऑप्टिमाइज़र ऑपरेशन को शॉर्ट-सर्किट करने की अधिक संभावना होगी, अगर उनमें से एक भी 0 के बराबर नहीं है , पहले एक संगणना करने की आवश्यकता के बिना।

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


3

कुछ सामान्य तर्क, यदि आपके पास कोई इंडेक्स नहीं है, तो मुझे नहीं लगता कि यह ज्यादा मायने रखेगा कि आप दोनों में से कौन सा समाधान चुनते हैं, दोनों ही खराब प्रदर्शन करेंगे। यदि आप दूसरी ओर एक या एक से अधिक स्तंभों पर एक सूचकांक को विधेय में समर्पित करते हैं, तो संभवतः दूसरा एक से बेहतर प्रदर्शन करेगा, क्योंकि दूसरा संभवत: सूचकांक का उपयोग करने में सक्षम नहीं होगा।

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


2

यह एक साधारण प्रश्न है

नहीं ऐसा नहीं है। यह (इस तरह का) सवाल है जो दिन में कई डीबीए और सॉफ़्टवेयर डेवलपर्स को बाहर करता है, और यह सब लेकिन तुच्छ है।

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

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

फिर, यह अन्य छोटे विवरणों की किसी भी राशि पर निर्भर कर सकता है, उदाहरण के लिए कि आपका DB डेटा कैसे संग्रहीत करता है, यदि आपके पास उप-चयन / जोड़ हैं जो योजना अनुकूलक आदि के लिए समस्या को भ्रमित करते हैं। आशावादी आपको भिन्न निष्पादन योजना दे सकता है आपके पास कितनी पंक्तियाँ हैं ...

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


0

यह स्पष्ट हो सकता है, लेकिन यदि स्तंभ हैं INT, तो तब a+b+cभी शून्य के बराबर हो सकता है, जब उनमें से कोई भी वास्तव में शून्य नहीं हो। आप दो अलग चीजों का परीक्षण कर रहे हैं!


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