बनाम भिन्न द्वारा समूह का उपयोग करते समय विशाल प्रदर्शन अंतर


81

मैं एक HSQLDBसर्वर पर 500 000 प्रविष्टियों वाली तालिका के साथ कुछ परीक्षण कर रहा हूं । तालिका में कोई संकेत नहीं है। 5000 अलग-अलग व्यावसायिक कुंजी हैं। मुझे उनकी एक सूची चाहिए। स्वाभाविक रूप से मैंने एक DISTINCTप्रश्न के साथ शुरू किया था :

SELECT DISTINCT business_key FROM memory WHERE
   concept <> 'case' or 
   attrib <> 'status' or 
   value <> 'closed'

इसमें लगभग 90 सेकंड लगते हैं !!!

फिर मैंने प्रयोग करने की कोशिश की GROUP BY:

SELECT business_key FROM memory WHERE
       concept <> 'case' or 
       attrib <> 'status' or 
       value <> 'closed'
GROUP BY business_key

और 1 सेकंड लगता है !!!

मेरे द्वारा चलाए गए अंतर का पता लगाने की कोशिश की जा रही है EXLAIN PLAN FORलेकिन यह दोनों प्रश्नों के लिए समान जानकारी देता है।

EXLAIN PLAN FOR DISTINCT ...

isAggregated=[false]
columns=[
  COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
  join type=INNER
  table=MEMORY
  alias=M
  access=FULL SCAN
  condition = [    index=SYS_IDX_SYS_PK_10057_10058
    other condition=[
    OR arg_left=[
     OR arg_left=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
       VALUE = case, TYPE = CHARACTER]] arg_right=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
       VALUE = status, TYPE = CHARACTER]]] arg_right=[
     NOT_EQUAL arg_left=[
      COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
      VALUE = closed, TYPE = CHARACTER]]]
  ]
]]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks

EXLAIN PLAN FOR SELECT ... GROUP BY ...

isDistinctSelect=[false]
isGrouped=[true]
isAggregated=[false]
columns=[
  COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
  join type=INNER
  table=MEMORY
  alias=M
  access=FULL SCAN
  condition = [    index=SYS_IDX_SYS_PK_10057_10058
    other condition=[
    OR arg_left=[
     OR arg_left=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
       VALUE = case, TYPE = CHARACTER]] arg_right=[
      NOT_EQUAL arg_left=[
       COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
       VALUE = status, TYPE = CHARACTER]]] arg_right=[
     NOT_EQUAL arg_left=[
      COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
      VALUE = closed, TYPE = CHARACTER]]]
  ]
]]
groupColumns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks

संपादित करें : मैंने अतिरिक्त परीक्षण किए। HSQLDBसभी अलग-अलग व्यावसायिक कुंजियों के साथ 500 000 रिकॉर्ड के साथ, प्रदर्शन DISTINCTअब बेहतर है - 3 सेकंड, बनाम GROUP BYजिसमें लगभग 9 सेकंड लगे।

में MySQLदोनों प्रश्नों ही पहिले:

MySQL: 500 000 पंक्तियाँ - 5 000 अलग-अलग व्यावसायिक कुंजियाँ: दोनों प्रश्न: 0.5 सेकंड MySQL: 500 000 पंक्तियाँ - सभी अलग-अलग व्यावसायिक कुंजियाँ: SELECT DISTINCT ...- 11 सेकंड SELECT ... GROUP BY business_key- 13 सेकंड

तो समस्या केवल से संबंधित है HSQLDB

मैं बहुत आभारी रहूंगा अगर कोई समझा सकता है कि इतना कठोर अंतर क्यों है।


2
कृपया परिणाम दिखाएं EXPLAIN PLANऔर DISTINCTक्वेरी को चलाने का प्रयास करें जब आप यह GROUP BYदेखने के लिए दौड़ें कि क्या कुछ कैशिंग समयरेखा को कम कर रहा है ...
याहिया

यह देखते हुए कि आपको प्रत्येक क्वेरी के लिए एक ही योजना मिलती है, ऐसा लगता है कि या तो तालिका डेटा या परिणाम कैश किया गया है।
अष्ट

मैंने उन्हें कई बार दौड़ाया कि विश्वास करो कि कैशिंग एक मुद्दा नहीं है। मैं EXLAIN PLAN FORआउटपुट पोस्ट कर रहा हूं ।
मार्टिन दिमित्रोव

मेरे पास एक विचार है, लेकिन मुझे वास्तव में यकीन नहीं है - कृपया कोशिश करें SELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed')- यह वही प्रदर्शन दिखाने के लिए चाहिए जिसे आप GROUP BYIF के साथ देखते हैं मेरा विचार सही है।
याहिया

@ याहिया: अभी भी बहुत धीमी गति से - 94 सेकंड। मैं MySQL में एक ही
मार्टिन दिमित्रोव

जवाबों:


77

दो प्रश्न एक ही प्रश्न को व्यक्त करते हैं। जाहिरा तौर पर क्वेरी ऑप्टिमाइज़र दो अलग-अलग निष्पादन योजनाओं को चुनता है। मेरा अनुमान है कि distinctदृष्टिकोण को निष्पादित किया जाएगा:

  • सभी business_keyमानों को एक अस्थायी तालिका में कॉपी करें
  • अस्थायी तालिका को क्रमबद्ध करें
  • अस्थायी तालिका को स्कैन करें, प्रत्येक आइटम को लौटाएं जो पहले से अलग है

group byकी तरह क्रियान्वित किया जा सकता है:

  • पूर्ण तालिका स्कैन, के प्रत्येक मान के भंडारण के business keyएक hashtable में
  • हैशटेबल की चाबी लौटाएं

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

चूंकि आपके पास पर्याप्त मेमोरी या कुछ अलग-अलग कुंजियाँ हैं, इसलिए दूसरी विधि पहले से बेहतर प्रदर्शन करती है। दो निष्पादन योजनाओं के बीच 10x या 100x के प्रदर्शन अंतर को देखना असामान्य नहीं है।


उत्तर के लिए धन्यवाद। क्या आपके अनुमान EXPLAINआउटपुट से स्पष्ट हैं ? दोनों मुझे एक जैसे लगते हैं।
मार्टिन दिमित्रोव 10

जहाँ तक मैं देख सकता हूँ, योजना यह निर्दिष्ट नहीं करती है कि यह कैसे जुड़ने पर अमल करेगा। मुझे भी यकीन नहीं है कि यह एक शामिल क्यों निष्पादित करेगा। यह शायद समझाने के उत्पादन को पढ़ने के लिए एक HSQLDB विशेषज्ञ लेता है।
एंडोमर

जैसा कि उत्तर इंगित करता है, दूसरी विधि अधिक मेमोरी का उपयोग करती है और कचरा संग्रह (जीसी) को भी अक्सर मार सकती है। यदि आप JVM मेमोरी आवंटन को बढ़ाते हैं, तो दो क्वेरी समय के बीच बहुत बड़ा अंतर नहीं होना चाहिए।
फ्रेड्ट

मैंने तालिका में सभी अलग-अलग कुंजी दर्ज करके अतिरिक्त परीक्षण किया (ऊपर देखें)। क्या आपको लगता है कि परिणाम आपकी बात साबित करता है? बहुत बहुत धन्यवाद।
मार्टिन दिमित्रोव

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