बड़े डेटासेट को संभालने के लिए, वितरित डेटाबेस विभाजन और बकेटिंग जैसी रणनीतियों को पेश करते हैं। डेटा को विशिष्ट नियमों के आधार पर छोटी इकाइयों में विभाजित किया जाता है और विभिन्न नोड्स में वितरित किया जाता है ताकि डेटाबेस उच्च प्रदर्शन और डेटा प्रबंधन लचीलेपन के लिए समानांतर प्रसंस्करण कर सकें।
कई डेटाबेस की तरह, अपाचे डोरिस डेटा को विभाजनों में विभाजित करता है, और फिर विभाजन को आगे बकेट में विभाजित किया जाता है। विभाजन आमतौर पर समय या अन्य निरंतर मानों द्वारा परिभाषित किए जाते हैं। यह क्वेरी इंजन को अप्रासंगिक डेटा श्रेणियों को छाँटकर क्वेरी के दौरान लक्ष्य डेटा को जल्दी से ढूँढने की अनुमति देता है।
दूसरी ओर, बकेटिंग एक या अधिक कॉलमों के हैश मानों के आधार पर डेटा वितरित करती है, जो डेटा के असंतुलन को रोकती है।
संस्करण 2.1.0 से पहले, अपाचे डोरिस में डेटा विभाजन बनाने के दो तरीके थे:
मैनुअल विभाजन : उपयोगकर्ता तालिका निर्माण कथन में विभाजन निर्दिष्ट करते हैं या बाद में DDL कथनों के माध्यम से उन्हें संशोधित करते हैं।
गतिशील विभाजन : सिस्टम स्वचालित रूप से डेटा अंतर्ग्रहण समय के आधार पर पूर्व-निर्धारित सीमा के भीतर विभाजन को बनाए रखता है।
अपाचे डोरिस 2.1.0 में, हमने ऑटो पार्टिशन पेश किया है। यह RANGE या LIST द्वारा डेटा विभाजन का समर्थन करता है और स्वचालित विभाजन के शीर्ष पर लचीलेपन को और बढ़ाता है।
डेटा वितरण के डिजाइन में, हम विभाजन नियोजन पर अधिक ध्यान केंद्रित करते हैं क्योंकि विभाजन स्तंभों और विभाजन अंतरालों का चुनाव वास्तविक डेटा वितरण पैटर्न पर बहुत अधिक निर्भर करता है, और एक अच्छा विभाजन डिजाइन तालिका की क्वेरी और भंडारण दक्षता में काफी हद तक सुधार कर सकता है।
डोरिस में, डेटा टेबल को विभाजनों में और फिर पदानुक्रमिक तरीके से बकेट में विभाजित किया जाता है। उसी बकेट के भीतर का डेटा फिर एक डेटा टैबलेट बनाता है, जो डेटा प्रतिकृति, इंटर-क्लस्टर डेटा शेड्यूलिंग और लोड बैलेंसिंग के लिए डोरिस में न्यूनतम भौतिक भंडारण इकाई है।
डोरिस उपयोगकर्ताओं को RANGE और LIST द्वारा मैन्युअल रूप से डेटा विभाजन बनाने की अनुमति देता है।
लॉग और ट्रांजेक्शन रिकॉर्ड जैसे टाइम-स्टैम्प्ड डेटा के लिए, उपयोगकर्ता आमतौर पर समय आयाम के आधार पर विभाजन बनाते हैं। यहाँ CREATE TABLE कथन का एक उदाहरण दिया गया है:
CREATE TABLE IF NOT EXISTS example_range_tbl ( `user_id` LARGEINT NOT NULL COMMENT "User ID", `date` DATE NOT NULL COMMENT "Data import date", `timestamp` DATETIME NOT NULL COMMENT "Data import timestamp", `city` VARCHAR(20) COMMENT "Location of user", `age` SMALLINT COMMENT "Age of user", `sex` TINYINT COMMENT "Sex of user", `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "Last visit date of user", `cost` BIGINT SUM DEFAULT "0" COMMENT "User consumption", `max_dwell_time` INT MAX DEFAULT "0" COMMENT "Maximum dwell time of user", `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "Minimum dwell time of user" ) ENGINE=OLAP AGGREGATE KEY(`user_id`, `date`, `timestamp`, `city`, `age`, `sex`) PARTITION BY RANGE(`date`) ( PARTITION `p201701` VALUES LESS THAN ("2017-02-01"), PARTITION `p201702` VALUES LESS THAN ("2017-03-01"), PARTITION `p201703` VALUES LESS THAN ("2017-04-01"), PARTITION `p2018` VALUES [("2018-01-01"), ("2019-01-01")) ) DISTRIBUTED BY HASH(`user_id`) BUCKETS 16 PROPERTIES ( "replication_num" = "1" );
तालिका को डेटा आयात date
के अनुसार विभाजित किया गया है, और 4 विभाजन पहले से बनाए गए हैं। प्रत्येक विभाजन के भीतर, डेटा को user_id
के हैश मान के आधार पर 16 बकेट में विभाजित किया गया है।
इस विभाजन और बकेटिंग डिज़ाइन के साथ, 2018 के बाद से डेटा क्वेरी करते समय, सिस्टम को केवल p2018
विभाजन को स्कैन करने की आवश्यकता होती है। क्वेरी SQL इस तरह दिखता है:
mysql> desc select count() from example_range_tbl where date >= '20180101'; +--------------------------------------------------------------------------------------+ | Explain String(Nereids Planner) | +--------------------------------------------------------------------------------------+ | PLAN FRAGMENT 0 | | OUTPUT EXPRS: | | count(*)[#11] | | PARTITION: UNPARTITIONED | | | | ...... | | | | 0:VOlapScanNode(193) | | TABLE: test.example_range_tbl(example_range_tbl), PREAGGREGATION: OFF. | | PREDICATES: (date[#1] >= '2018-01-01') | | partitions=1/4 (p2018), tablets=16/16, tabletList=561490,561492,561494 ... | | cardinality=0, avgRowSize=0.0, numNodes=1 | | pushAggOp=NONE | | | +--------------------------------------------------------------------------------------+
यदि डेटा विभाजनों में असमान रूप से वितरित किया जाता है, तो हैश-आधारित बकेटिंग तंत्र user_id
आधार पर डेटा को और विभाजित कर सकता है। यह क्वेरी और स्टोरेज के दौरान कुछ मशीनों पर लोड असंतुलन से बचने में मदद करता है।
हालाँकि, वास्तविक दुनिया के व्यावसायिक परिदृश्यों में, एक क्लस्टर में हजारों टेबल हो सकती हैं, जिसका अर्थ है कि उन्हें मैन्युअल रूप से प्रबंधित करना असंभव है।
CREATE TABLE `DAILY_TRADE_VALUE` ( `TRADE_DATE` datev2 NOT NULL COMMENT 'Trade date', `TRADE_ID` varchar(40) NOT NULL COMMENT 'Trade ID', ...... ) UNIQUE KEY(`TRADE_DATE`, `TRADE_ID`) PARTITION BY RANGE(`TRADE_DATE`) ( PARTITION p_200001 VALUES [('2000-01-01'), ('2000-02-01')), PARTITION p_200002 VALUES [('2000-02-01'), ('2000-03-01')), PARTITION p_200003 VALUES [('2000-03-01'), ('2000-04-01')), PARTITION p_200004 VALUES [('2000-04-01'), ('2000-05-01')), PARTITION p_200005 VALUES [('2000-05-01'), ('2000-06-01')), PARTITION p_200006 VALUES [('2000-06-01'), ('2000-07-01')), PARTITION p_200007 VALUES [('2000-07-01'), ('2000-08-01')), PARTITION p_200008 VALUES [('2000-08-01'), ('2000-09-01')), PARTITION p_200009 VALUES [('2000-09-01'), ('2000-10-01')), PARTITION p_200010 VALUES [('2000-10-01'), ('2000-11-01')), PARTITION p_200011 VALUES [('2000-11-01'), ('2000-12-01')), PARTITION p_200012 VALUES [('2000-12-01'), ('2001-01-01')), PARTITION p_200101 VALUES [('2001-01-01'), ('2001-02-01')), ...... ) DISTRIBUTED BY HASH(`TRADE_DATE`) BUCKETS 10 PROPERTIES ( ...... );
उपरोक्त उदाहरण में, डेटा को मासिक आधार पर विभाजित किया जाता है। इसके लिए डेटाबेस एडमिनिस्ट्रेटर (DBA) को हर महीने मैन्युअल रूप से एक नया विभाजन जोड़ना पड़ता है और नियमित रूप से टेबल स्कीमा को बनाए रखना पड़ता है। वास्तविक समय डेटा प्रोसेसिंग के मामले की कल्पना करें, जहाँ आपको प्रतिदिन या यहाँ तक कि प्रति घंटे विभाजन बनाने की आवश्यकता हो सकती है, मैन्युअल रूप से ऐसा करना अब कोई विकल्प नहीं है। इसीलिए हमने डायनेमिक पार्टीशन की शुरुआत की है।
डायनेमिक पार्टीशन के ज़रिए, डोरिस स्वचालित रूप से डेटा पार्टीशन बनाता है और पुनः प्राप्त करता है, जब तक कि उपयोगकर्ता पार्टीशन यूनिट, ऐतिहासिक पार्टीशन की संख्या और भविष्य के पार्टीशन की संख्या निर्दिष्ट करता है। यह कार्यक्षमता डोरिस फ्रंटएंड पर एक निश्चित थ्रेड पर निर्भर करती है। यह लगातार नए पार्टीशन बनाने या पुराने पार्टीशन को पुनः प्राप्त करने के लिए पोल करता है और जाँच करता है, और टेबल के पार्टीशन स्कीमा को अपडेट करता है।
यह दिन के हिसाब से विभाजित टेबल के लिए CREATE TABLE कथन का एक उदाहरण है। start
और end
पैरामीटर क्रमशः -7
और 3
पर सेट किए गए हैं, जिसका अर्थ है कि अगले 3 दिनों के लिए डेटा विभाजन पहले से बनाए जाएँगे, और 7 दिनों से पुराने ऐतिहासिक विभाजन पुनः प्राप्त किए जाएँगे।
CREATE TABLE `DAILY_TRADE_VALUE` ( `TRADE_DATE` datev2 NOT NULL COMMENT 'Trade date', `TRADE_ID` varchar(40) NOT NULL COMMENT 'Trade ID', ...... ) UNIQUE KEY(`TRADE_DATE`, `TRADE_ID`) PARTITION BY RANGE(`TRADE_DATE`) () DISTRIBUTED BY HASH(`TRADE_DATE`) BUCKETS 10 PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "DAY", "dynamic_partition.start" = "-7", "dynamic_partition.end" = "3", "dynamic_partition.prefix" = "p", "dynamic_partition.buckets" = "10" );
समय के साथ, तालिका हमेशा [current date - 7, current date + 3]
की सीमा के भीतर विभाजन बनाए रखेगी। डायनेमिक विभाजन विशेष रूप से वास्तविक समय डेटा अंतर्ग्रहण परिदृश्यों के लिए उपयोगी है, जैसे कि जब ODS (ऑपरेशनल डेटा स्टोर) परत सीधे काफ़्का जैसे बाहरी स्रोतों से डेटा प्राप्त करती है।
start
और end
पैरामीटर विभाजनों के लिए एक निश्चित सीमा निर्धारित करते हैं, जिससे उपयोगकर्ता को केवल इस सीमा के भीतर विभाजनों का प्रबंधन करने की अनुमति मिलती है। हालाँकि, यदि उपयोगकर्ता को अधिक ऐतिहासिक डेटा शामिल करने की आवश्यकता है, तो उन्हें start
मान डायल करना होगा, और इससे क्लस्टर में अनावश्यक मेटाडेटा ओवरहेड हो सकता है।
इसलिए, डायनेमिक पार्टीशन को लागू करते समय, मेटाडेटा प्रबंधन की सुविधा और दक्षता के बीच एक समझौता होता है।
जैसे-जैसे व्यवसाय की जटिलता बढ़ती जाती है, गतिशील विभाजन अपर्याप्त होता जाता है क्योंकि:
इन कार्यात्मक सीमाओं को देखते हुए, हमने एक नए विभाजन तंत्र की योजना बनाना शुरू किया, जो विभाजन प्रबंधन को स्वचालित कर सके और डेटा तालिका रखरखाव को सरल बना सके।
हमने पाया कि आदर्श विभाजन कार्यान्वयन इस प्रकार होना चाहिए:
पहला स्वचालन के लिए है और दूसरा लचीलेपन के लिए। इन दोनों को साकार करने का सार विभाजन निर्माण को वास्तविक डेटा के साथ जोड़ना है।
फिर हमने निम्नलिखित के बारे में सोचना शुरू किया: क्या होगा अगर हम टेबल निर्माण के दौरान या नियमित पोलिंग के माध्यम से ऐसा करने के बजाय डेटा के अंतर्ग्रहण होने तक विभाजन बनाने को रोक दें? विभाजन वितरण को पहले से बनाने के बजाय, हम "डेटा-टू-पार्टीशन" मैपिंग नियमों को परिभाषित कर सकते हैं ताकि डेटा आने के बाद विभाजन बनाए जा सकें।
मैनुअल पार्टिशन की तुलना में, यह पूरी प्रक्रिया पूरी तरह से स्वचालित होगी, जिससे मानवीय रखरखाव की आवश्यकता समाप्त हो जाएगी। डायनेमिक पार्टिशन की तुलना में, यह उन पार्टिशन से बचता है जिनका उपयोग नहीं किया जाता है या ऐसे पार्टिशन जिनकी आवश्यकता है लेकिन वे मौजूद नहीं हैं।
अपाचे डोरिस 2.1.0 के साथ, हम उपरोक्त योजना को सफल बनाते हैं। डेटा अंतर्ग्रहण के दौरान, डोरिस कॉन्फ़िगर किए गए नियमों के आधार पर डेटा विभाजन बनाता है। डेटा प्रोसेसिंग और वितरण के लिए जिम्मेदार डोरिस बैकएंड नोड्स निष्पादन योजना के डेटासिंक ऑपरेटर में डेटा की प्रत्येक पंक्ति के लिए उपयुक्त विभाजन खोजने का प्रयास करेंगे। यह अब ऐसे डेटा को फ़िल्टर नहीं करता है जो किसी मौजूदा विभाजन में फिट नहीं होता है या ऐसी स्थिति के लिए त्रुटि की रिपोर्ट करता है, लेकिन सभी अंतर्ग्रहण किए गए डेटा के लिए स्वचालित रूप से विभाजन उत्पन्न करता है।
RANGE द्वारा ऑटो पार्टिशन समय आयाम के आधार पर एक अनुकूलित विभाजन समाधान प्रदान करता है। पैरामीटर कॉन्फ़िगरेशन के संदर्भ में यह डायनेमिक पार्टिशन से अधिक लचीला है। इसके लिए सिंटैक्स इस प्रकार है:
AUTO PARTITION BY RANGE (FUNC_CALL_EXPR) () FUNC_CALL_EXPR ::= DATE_TRUNC ( <partition_column>, '<interval>' )
उपरोक्त <partition_column>
विभाजन स्तंभ है (अर्थात, वह स्तंभ जिस पर विभाजन आधारित है)। <interval>
विभाजन इकाई को निर्दिष्ट करता है, जो प्रत्येक विभाजन की वांछित चौड़ाई है।
उदाहरण के लिए, यदि विभाजन स्तंभ k0
है और आप महीने के अनुसार विभाजन करना चाहते हैं, तो विभाजन कथन AUTO PARTITION BY RANGE (DATE_TRUNC(k0, 'month'))
होगा। सभी आयातित डेटा के लिए, सिस्टम विभाजन के बाएं अंत बिंदु की गणना करने के लिए DATE_TRUNC(k0, 'month')
को कॉल करेगा, और फिर एक interval
जोड़कर दाएं अंत बिंदु की गणना करेगा।
अब, हम डायनामिक पार्टीशन पर पिछले अनुभाग में प्रस्तुत DAILY_TRADE_VALUE
तालिका पर ऑटो पार्टीशन लागू कर सकते हैं।
CREATE TABLE DAILY_TRADE_VALUE ( `TRADE_DATE` DATEV2 NOT NULL COMMENT 'Trade Date', `TRADE_ID` VARCHAR(40) NOT NULL COMMENT 'Trade ID', ...... ) AUTO PARTITION BY RANGE (DATE_TRUNC(`TRADE_DATE`, 'month')) () DISTRIBUTED BY HASH(`TRADE_DATE`) BUCKETS 10 PROPERTIES ( ...... );
कुछ डेटा आयात करने के बाद, हमें ये विभाजन प्राप्त होते हैं:
mysql> show partitions from DAILY_TRADE_VALUE; Empty set (0.10 sec) mysql> insert into DAILY_TRADE_VALUE values ('2015-01-01', 1), ('2020-01-01', 2), ('2024-03-05', 10000), ('2024-03-06', 10001); Query OK, 4 rows affected (0.24 sec) {'label':'label_2a7353a3f991400e_ae731988fa2bc568', 'status':'VISIBLE', 'txnId':'85097'} mysql> show partitions from DAILY_TRADE_VALUE; +-------------+-----------------+----------------+---------------------+--------+--------------+--------------------------------------------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | PartitionId | PartitionName | VisibleVersion | VisibleVersionTime | State | PartitionKey | Range | DistributionKey | Buckets | ReplicationNum | StorageMedium | CooldownTime | RemoteStoragePolicy | LastConsistencyCheckTime | DataSize | IsInMemory | ReplicaAllocation | IsMutable | SyncWithBaseTables | UnsyncTables | +-------------+-----------------+----------------+---------------------+--------+--------------+--------------------------------------------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | 588395 | p20150101000000 | 2 | 2024-06-01 19:02:40 | NORMAL | TRADE_DATE | [types: [DATEV2]; keys: [2015-01-01]; ..types: [DATEV2]; keys: [2015-02-01]; ) | TRADE_DATE | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 588437 | p20200101000000 | 2 | 2024-06-01 19:02:40 | NORMAL | TRADE_DATE | [types: [DATEV2]; keys: [2020-01-01]; ..types: [DATEV2]; keys: [2020-02-01]; ) | TRADE_DATE | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 588416 | p20240301000000 | 2 | 2024-06-01 19:02:40 | NORMAL | TRADE_DATE | [types: [DATEV2]; keys: [2024-03-01]; ..types: [DATEV2]; keys: [2024-04-01]; ) | TRADE_DATE | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | +-------------+-----------------+----------------+---------------------+--------+--------------+--------------------------------------------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ 3 rows in set (0.09 sec)
जैसा कि दिखाया गया है, आयातित डेटा के लिए विभाजन स्वचालित रूप से बनाए जाते हैं, और यह ऐसे विभाजन नहीं बनाता जो मौजूदा डेटा की सीमा से परे हों।
LIST द्वारा ऑटो पार्टिशन का उद्देश्य गैर-समय-आधारित आयामों, जैसे कि region
और department
के आधार पर डेटा को विभाजित करना है। यह डायनेमिक पार्टिशन के लिए उस अंतर को भरता है, जो LIST द्वारा डेटा विभाजन का समर्थन नहीं करता है।
RANGE द्वारा ऑटो पार्टिशन समय आयाम के आधार पर एक अनुकूलित विभाजन समाधान प्रदान करता है। पैरामीटर कॉन्फ़िगरेशन के संदर्भ में यह डायनेमिक पार्टिशन से अधिक लचीला है। इसके लिए सिंटैक्स इस प्रकार है:
AUTO PARTITION BY LIST (`partition_col`) ()
यह city
विभाजन स्तंभ के रूप में उपयोग करते हुए LIST द्वारा स्वतः विभाजन का एक उदाहरण है:
mysql> CREATE TABLE `str_table` ( -> `city` VARCHAR NOT NULL, -> ...... -> ) -> DUPLICATE KEY(`city`) -> AUTO PARTITION BY LIST (`city`) -> () -> DISTRIBUTED BY HASH(`city`) BUCKETS 10 -> PROPERTIES ( -> ...... -> ); Query OK, 0 rows affected (0.09 sec) mysql> insert into str_table values ("Denver"), ("Boston"), ("Los_Angeles"); Query OK, 3 rows affected (0.25 sec) mysql> show partitions from str_table; +-------------+-----------------+----------------+---------------------+--------+--------------+-------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | PartitionId | PartitionName | VisibleVersion | VisibleVersionTime | State | PartitionKey | Range | DistributionKey | Buckets | ReplicationNum | StorageMedium | CooldownTime | RemoteStoragePolicy | LastConsistencyCheckTime | DataSize | IsInMemory | ReplicaAllocation | IsMutable | SyncWithBaseTables | UnsyncTables | +-------------+-----------------+----------------+---------------------+--------+--------------+-------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | 589685 | pDenver7 | 2 | 2024-06-01 20:12:37 | NORMAL | city | [types: [VARCHAR]; keys: [Denver]; ] | city | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 589643 | pLos5fAngeles11 | 2 | 2024-06-01 20:12:37 | NORMAL | city | [types: [VARCHAR]; keys: [Los_Angeles]; ] | city | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 589664 | pBoston8 | 2 | 2024-06-01 20:12:37 | NORMAL | city | [types: [VARCHAR]; keys: [Boston]; ] | city | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | +-------------+-----------------+----------------+---------------------+--------+--------------+-------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ 3 rows in set (0.10 sec)
डेनवर, बोस्टन और लॉस एंजिल्स के शहरों के लिए डेटा डालने के बाद, सिस्टम ने शहर के नामों के आधार पर स्वचालित रूप से संबंधित विभाजन बनाए। पहले, इस प्रकार का कस्टम विभाजन केवल मैन्युअल DDL कथनों के माध्यम से प्राप्त किया जा सकता था। इस तरह LIST द्वारा ऑटो पार्टिशन डेटाबेस रखरखाव को सरल बनाता है।
ऐतिहासिक विभाजनों को मैन्युअल रूप से समायोजित करें
उन तालिकाओं के लिए जो वास्तविक समय डेटा और कभी-कभी ऐतिहासिक अपडेट दोनों प्राप्त करती हैं, चूंकि ऑटो पार्टीशन ऐतिहासिक विभाजनों को स्वचालित रूप से पुनः प्राप्त नहीं करता है, इसलिए हम दो विकल्पों की अनुशंसा करते हैं:
ऑटो पार्टीशन का उपयोग करें, जो सामयिक ऐतिहासिक डेटा अपडेट के लिए स्वचालित रूप से पार्टीशन बनाएगा।
ऑटो पार्टीशन का उपयोग करें और ऐतिहासिक अपडेट को समायोजित करने के लिए मैन्युअल रूप से LESS THAN
पार्टीशन बनाएं। यह ऐतिहासिक और वास्तविक समय के डेटा को स्पष्ट रूप से अलग करने की अनुमति देता है और डेटा प्रबंधन को आसान बनाता है।
mysql> CREATE TABLE DAILY_TRADE_VALUE -> ( -> `TRADE_DATE` DATEV2 NOT NULL COMMENT 'Trade Date', -> `TRADE_ID` VARCHAR(40) NOT NULL COMMENT 'Trade ID' -> ) -> AUTO PARTITION BY RANGE (DATE_TRUNC(`TRADE_DATE`, 'DAY')) -> ( -> PARTITION `pHistory` VALUES LESS THAN ("2024-01-01") -> ) -> DISTRIBUTED BY HASH(`TRADE_DATE`) BUCKETS 10 -> PROPERTIES -> ( -> "replication_num" = "1" -> ); Query OK, 0 rows affected (0.11 sec) mysql> insert into DAILY_TRADE_VALUE values ('2015-01-01', 1), ('2020-01-01', 2), ('2024-03-05', 10000), ('2024-03-06', 10001); Query OK, 4 rows affected (0.25 sec) {'label':'label_96dc3d20c6974f4a_946bc1a674d24733', 'status':'VISIBLE', 'txnId':'85092'} mysql> show partitions from DAILY_TRADE_VALUE; +-------------+-----------------+----------------+---------------------+--------+--------------+--------------------------------------------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | PartitionId | PartitionName | VisibleVersion | VisibleVersionTime | State | PartitionKey | Range | DistributionKey | Buckets | ReplicationNum | StorageMedium | CooldownTime | RemoteStoragePolicy | LastConsistencyCheckTime | DataSize | IsInMemory | ReplicaAllocation | IsMutable | SyncWithBaseTables | UnsyncTables | +-------------+-----------------+----------------+---------------------+--------+--------------+--------------------------------------------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | 577871 | pHistory | 2 | 2024-06-01 08:53:49 | NORMAL | TRADE_DATE | [types: [DATEV2]; keys: [0000-01-01]; ..types: [DATEV2]; keys: [2024-01-01]; ) | TRADE_DATE | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 577940 | p20240305000000 | 2 | 2024-06-01 08:53:49 | NORMAL | TRADE_DATE | [types: [DATEV2]; keys: [2024-03-05]; ..types: [DATEV2]; keys: [2024-03-06]; ) | TRADE_DATE | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 577919 | p20240306000000 | 2 | 2024-06-01 08:53:49 | NORMAL | TRADE_DATE | [types: [DATEV2]; keys: [2024-03-06]; ..types: [DATEV2]; keys: [2024-03-07]; ) | TRADE_DATE | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | +-------------+-----------------+----------------+---------------------+--------+--------------+--------------------------------------------------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ 3 rows in set (0.10 sec)
शून्य विभाजन
LIST द्वारा ऑटो पार्टिशन के साथ, डोरिस NULL पार्टिशन में NULL मानों को संग्रहीत करने का समर्थन करता है। उदाहरण के लिए:
mysql> CREATE TABLE list_nullable -> ( -> `str` varchar NULL -> ) -> AUTO PARTITION BY LIST (`str`) -> () -> DISTRIBUTED BY HASH(`str`) BUCKETS auto -> PROPERTIES -> ( -> "replication_num" = "1" -> ); Query OK, 0 rows affected (0.10 sec) mysql> insert into list_nullable values ('123'), (''), (NULL); Query OK, 3 rows affected (0.24 sec) {'label':'label_f5489769c2f04f0d_bfb65510f9737fff', 'status':'VISIBLE', 'txnId':'85089'} mysql> show partitions from list_nullable; +-------------+---------------+----------------+---------------------+--------+--------------+------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | PartitionId | PartitionName | VisibleVersion | VisibleVersionTime | State | PartitionKey | Range | DistributionKey | Buckets | ReplicationNum | StorageMedium | CooldownTime | RemoteStoragePolicy | LastConsistencyCheckTime | DataSize | IsInMemory | ReplicaAllocation | IsMutable | SyncWithBaseTables | UnsyncTables | +-------------+---------------+----------------+---------------------+--------+--------------+------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ | 577297 | pX | 2 | 2024-06-01 08:19:21 | NORMAL | str | [types: [VARCHAR]; keys: [NULL]; ] | str | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 577276 | p0 | 2 | 2024-06-01 08:19:21 | NORMAL | str | [types: [VARCHAR]; keys: []; ] | str | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | | 577255 | p1233 | 2 | 2024-06-01 08:19:21 | NORMAL | str | [types: [VARCHAR]; keys: [123]; ] | str | 10 | 1 | HDD | 9999-12-31 23:59:59 | | NULL | 0.000 | false | tag.location.default: 1 | true | true | NULL | +-------------+---------------+----------------+---------------------+--------+--------------+------------------------------------+-----------------+---------+----------------+---------------+---------------------+---------------------+--------------------------+----------+------------+-------------------------+-----------+--------------------+--------------+ 3 rows in set (0.11 sec)
हालाँकि, RANGE द्वारा ऑटो पार्टिशन NULL पार्टिशन का समर्थन नहीं करता है, क्योंकि NULL मान सबसे छोटे LESS THAN
पार्टिशन में संग्रहीत किए जाएँगे, और इसके लिए उचित रेंज को विश्वसनीय रूप से निर्धारित करना असंभव है। यदि ऑटो पार्टिशन (-INFINITY, MIN_VALUE) की रेंज के साथ NULL पार्टिशन बनाता है, तो उत्पादन में इस पार्टिशन के अनजाने में डिलीट हो जाने का जोखिम होगा, क्योंकि MIN_VALUE सीमा इच्छित व्यावसायिक तर्क का सटीक रूप से प्रतिनिधित्व नहीं कर सकती है।
ऑटो पार्टिशन डायनेमिक पार्टिशन के अधिकांश उपयोग मामलों को कवर करता है, जबकि अपफ्रंट पार्टिशन नियम परिभाषा का लाभ भी देता है। एक बार नियम परिभाषित हो जाने के बाद, विभाजन निर्माण कार्य का बड़ा हिस्सा DBA के बजाय डोरिस द्वारा स्वचालित रूप से संभाला जाता है।
ऑटो पार्टीशन का उपयोग करने से पहले, प्रासंगिक सीमाओं को समझना महत्वपूर्ण है:
LIST द्वारा ऑटो पार्टिशन कई कॉलम के आधार पर विभाजन का समर्थन करता है, लेकिन प्रत्येक स्वचालित रूप से बनाए गए विभाजन में केवल एक ही मान होता है, और विभाजन का नाम लंबाई में 50 वर्णों से अधिक नहीं हो सकता है। ध्यान दें कि विभाजन नाम विशिष्ट नामकरण परंपराओं का पालन करते हैं, जिनका मेटाडेटा प्रबंधन के लिए विशेष निहितार्थ हैं। इसका मतलब है कि 50-वर्णों का पूरा स्थान उपयोगकर्ता के निपटान में नहीं है।
RANGE द्वारा स्वचालित विभाजन केवल एकल विभाजन कॉलम का समर्थन करता है, जो DATE या DATETIME प्रकार का होना चाहिए।
LIST द्वारा ऑटो पार्टिशन NULLABLE पार्टीशन कॉलम और NULL मानों को सम्मिलित करने का समर्थन करता है। RANGE द्वारा ऑटो पार्टिशन NULLABLE पार्टीशन कॉलम का समर्थन नहीं करता है।
अपाचे डोरिस 2.1.3 के बाद डायनेमिक पार्टीशन के साथ ऑटो पार्टीशन का उपयोग करना अनुशंसित नहीं है।
ऑटो पार्टीशन और डायनामिक पार्टीशन के बीच मुख्य कार्यात्मक अंतर, पार्टीशन निर्माण और विलोपन, समर्थित पार्टीशन प्रकार, तथा आयात प्रदर्शन पर उनके प्रभाव में निहित हैं।
डायनेमिक पार्टीशन समय-समय पर पार्टीशन बनाने और पुनः प्राप्त करने के लिए निश्चित थ्रेड का उपयोग करता है। यह केवल RANGE द्वारा विभाजन का समर्थन करता है। इसके विपरीत, ऑटो पार्टीशन RANGE और LIST द्वारा दोनों विभाजन का समर्थन करता है। यह डेटा अंतर्ग्रहण के दौरान विशिष्ट नियमों के आधार पर स्वचालित रूप से ऑन-डिमांड विभाजन बनाता है, जिससे स्वचालन और लचीलेपन का उच्च स्तर मिलता है।
डायनेमिक पार्टीशन डेटा इनजेक्शन की गति को धीमा नहीं करता है, जबकि ऑटो पार्टीशन कुछ समय का अतिरिक्त व्यय करता है क्योंकि यह पहले मौजूदा पार्टीशन की जांच करता है और फिर मांग पर नए पार्टीशन बनाता है। हम प्रदर्शन परीक्षण के परिणाम प्रस्तुत करेंगे।
यह भाग इस बारे में है कि ऑटो पार्टिशन मैकेनिज्म के साथ डेटा इंजेक्शन कैसे लागू किया जाता है, और हम स्ट्रीम लोड को एक उदाहरण के रूप में उपयोग करते हैं। जब डोरिस डेटा आयात शुरू करता है, तो डोरिस बैकएंड नोड्स में से एक समन्वयक की भूमिका निभाता है। यह प्रारंभिक डेटा प्रोसेसिंग कार्य के लिए जिम्मेदार है और फिर निष्पादन के लिए डेटा को उपयुक्त BE नोड्स, जिन्हें एक्जीक्यूटर्स के रूप में जाना जाता है, को भेजता है।
समन्वयक की निष्पादन पाइपलाइन के अंतिम डेटासिंक नोड में, डेटा को सफलतापूर्वक प्रेषित और संग्रहीत करने से पहले उसे सही विभाजनों, बकेटों और डोरिस बैकएंड नोड स्थानों पर रूट किया जाना चाहिए।
इस डेटा स्थानांतरण को सक्षम करने के लिए, समन्वयक और निष्पादक नोड संचार चैनल स्थापित करते हैं:
डेटा के लिए सही विभाजन निर्धारित करने की प्रक्रिया के दौरान ऑटो पार्टीशन इस प्रकार काम करता है:
पहले, ऑटो पार्टिशन के बिना, जब किसी टेबल में आवश्यक पार्टिशन नहीं होता था, तो डोरिस में व्यवहार BE नोड्स के लिए तब तक त्रुटियाँ जमा करना होता था जब तक कि DATA_QUALITY_ERROR
रिपोर्ट नहीं की जाती थी। अब, ऑटो पार्टिशन सक्षम होने पर, डोरिस फ्रंटएंड को आवश्यक पार्टिशन को तुरंत बनाने के लिए अनुरोध शुरू किया जाएगा। पार्टिशन निर्माण लेनदेन पूरा होने के बाद, डोरिस फ्रंटएंड समन्वयक को जवाब देता है, जो फिर डेटा अंतर्ग्रहण प्रक्रिया को जारी रखने के लिए संबंधित संचार चैनल (नोड चैनल और टैबलेट चैनल) खोलता है। यह उपयोगकर्ताओं के लिए एक सहज अनुभव है।
वास्तविक दुनिया के क्लस्टर वातावरण में, डोरिस फ्रंटएंड द्वारा विभाजन निर्माण पूरा करने के लिए प्रतीक्षा करने में समन्वयक द्वारा बिताया गया समय बड़े ओवरहेड्स का कारण बन सकता है। यह थ्रिफ्ट RPC कॉल की अंतर्निहित विलंबता के साथ-साथ उच्च लोड स्थितियों के तहत फ्रंटएंड पर लॉक विवाद के कारण होता है।
ऑटो पार्टिशन में डेटा अंतर्ग्रहण दक्षता में सुधार करने के लिए, डोरिस ने बैचिंग को लागू किया है ताकि FE पर किए जाने वाले RPC कॉल की संख्या को काफी हद तक कम किया जा सके। यह डेटा लेखन संचालन के लिए उल्लेखनीय प्रदर्शन वृद्धि लाता है।
ध्यान दें कि जब FE मास्टर विभाजन निर्माण लेनदेन पूरा करता है, तो नया विभाजन तुरंत दिखाई देने लगता है। हालाँकि, यदि आयात प्रक्रिया अंततः विफल हो जाती है या रद्द हो जाती है, तो बनाए गए विभाजन स्वचालित रूप से पुनः प्राप्त नहीं होते हैं।
हमने डोरिस में ऑटो पार्टीशन के प्रदर्शन और स्थिरता का परीक्षण किया, जिसमें विभिन्न उपयोग के मामले शामिल थे:
केस 1 : 1 फ्रंटएंड + 3 बैकएंड; 6 यादृच्छिक रूप से उत्पन्न डेटासेट, प्रत्येक में 100 मिलियन पंक्तियाँ और 2,000 विभाजन; 6 डेटासेट को 6 तालिकाओं में समवर्ती रूप से शामिल किया गया
उद्देश्य : उच्च दबाव में ऑटो पार्टीशन के प्रदर्शन का मूल्यांकन करना और किसी भी प्रदर्शन गिरावट की जांच करना।
परिणाम : ऑटो पार्टीशन से औसतन 5% से कम प्रदर्शन हानि होती है, तथा सभी आयात लेनदेन स्थिर रूप से चलते हैं।
केस 2 : 1 फ्रंटएंड + 3 बैकएंड; रूटीन लोड द्वारा फ्लिंक से प्रति सेकंड 100 पंक्तियों को अंतर्ग्रहण करना; क्रमशः 1, 10, और 20 समवर्ती लेनदेन (तालिकाओं) के साथ परीक्षण करना
उद्देश्य : विभिन्न समवर्ती स्तरों के अंतर्गत ऑटो विभाजन के साथ उत्पन्न होने वाली किसी भी संभावित डेटा बैकलॉग समस्या की पहचान करना।
परिणाम : ऑटो पार्टीशन सक्षम होने या न होने पर, परीक्षण किए गए सभी समवर्ती स्तरों पर बिना किसी बैकप्रेशर समस्या के डेटा अंतर्ग्रहण सफल रहा, यहां तक कि 20 समवर्ती लेनदेन पर भी जब CPU उपयोग 100% के करीब पहुंच गया था।
इन परीक्षणों के परिणामों का निष्कर्ष यह है कि डेटा अंतर्ग्रहण प्रदर्शन पर ऑटो पार्टीशन को सक्षम करने का प्रभाव न्यूनतम है।
अपाचे डोरिस 2.1.0 के बाद से ऑटो पार्टिशन ने DDL और पार्टीशन प्रबंधन को सरल बना दिया है। यह बड़े पैमाने पर डेटा प्रोसेसिंग में उपयोगी है और उपयोगकर्ताओं के लिए अन्य डेटाबेस सिस्टम से अपाचे डोरिस में माइग्रेट करना आसान बनाता है।
इसके अलावा, हम अधिक जटिल डेटा प्रकारों का समर्थन करने के लिए ऑटो पार्टीशन की क्षमताओं का विस्तार करने के लिए प्रतिबद्ध हैं।
रेंज द्वारा ऑटो पार्टीशन की योजनाएँ:
संख्यात्मक मानों का समर्थन करें;
उपयोगकर्ताओं को विभाजन सीमा की बाईं और दाईं सीमा निर्दिष्ट करने की अनुमति देना।
सूची द्वारा ऑटो विभाजन की योजनाएँ: