বড় ডেটাসেটগুলি পরিচালনা করতে, বিতরণ করা ডেটাবেসগুলি পার্টিশন এবং বাকেটিংয়ের মতো কৌশলগুলি প্রবর্তন করে। ডেটাকে নির্দিষ্ট নিয়মের উপর ভিত্তি করে ছোট ছোট ইউনিটে ভাগ করা হয় এবং বিভিন্ন নোড জুড়ে বিতরণ করা হয় যাতে ডাটাবেসগুলি উচ্চতর কর্মক্ষমতা এবং ডেটা ব্যবস্থাপনার নমনীয়তার জন্য সমান্তরাল প্রক্রিয়াকরণ করতে পারে।
অনেক ডাটাবেসের মতো, ডেটাকে পার্টিশনে ভাগ করে এবং তারপরে একটি পার্টিশনকে আরও বালতিতে ভাগ করা হয়। পার্টিশনগুলি সাধারণত সময় বা অন্যান্য ক্রমাগত মান দ্বারা সংজ্ঞায়িত করা হয়। এটি কোয়েরি ইঞ্জিনগুলিকে অপ্রাসঙ্গিক ডেটা রেঞ্জগুলি ছাঁটাই করে ক্যোয়ারী চলাকালীন টার্গেট ডেটা দ্রুত সনাক্ত করতে দেয়।
অন্যদিকে, বাকেটিং এক বা একাধিক কলামের হ্যাশ মানের উপর ভিত্তি করে ডেটা বিতরণ করে, যা ডেটা স্কুকে বাধা দেয়।
সংস্করণ এর আগে, দুটি উপায়ে আপনি Apache Doris-এ ডেটা পার্টিশন তৈরি করতে পারেন:
: ব্যবহারকারীরা টেবিল তৈরির বিবৃতিতে পার্টিশনগুলি নির্দিষ্ট করে বা পরে DDL স্টেটমেন্টের মাধ্যমে তাদের পরিবর্তন করে।
: সিস্টেমটি স্বয়ংক্রিয়ভাবে ডেটা ইনজেশন সময়ের উপর ভিত্তি করে একটি পূর্ব-নির্ধারিত পরিসরের মধ্যে পার্টিশনগুলি বজায় রাখে।
Apache Doris 2.1.0 এ, আমরা চালু করেছি। এটি RANGE বা তালিকা দ্বারা ডেটা বিভাজন সমর্থন করে এবং স্বয়ংক্রিয় পার্টিশনের উপরে নমনীয়তা বাড়ায়।
ডাটা ডিস্ট্রিবিউশনের ডিজাইনে, আমরা পার্টিশন প্ল্যানিং এর উপর বেশি ফোকাস করি কারণ পার্টিশন কলাম এবং পার্টিশন ব্যবধানের পছন্দ প্রকৃত ডাটা ডিস্ট্রিবিউশন প্যাটার্নের উপর অনেক বেশি নির্ভর করে এবং একটি ভালো পার্টিশন ডিজাইন টেবিলের ক্যোয়ারী এবং স্টোরেজ দক্ষতাকে অনেকাংশে উন্নত করতে পারে।
ডরিসে, ডেটা টেবিলটি পার্টিশনে বিভক্ত এবং তারপরে ক্রমানুসারে বালতি। একই বালতির মধ্যে থাকা ডেটা তারপরে একটি ডেটা ট্যাবলেট তৈরি করে, যা ডেটা প্রতিলিপি, আন্তঃ-ক্লাস্টার ডেটা শিডিউলিং এবং লোড ব্যালেন্সিংয়ের জন্য ডরিসের ন্যূনতম ফিজিক্যাল স্টোরেজ ইউনিট।
ডরিস ব্যবহারকারীদের RANGE এবং তালিকা দ্বারা ম্যানুয়ালি ডেটা পার্টিশন তৈরি করতে দেয়।
লগ এবং লেনদেন রেকর্ডের মতো টাইম-স্ট্যাম্পড ডেটার জন্য, ব্যবহারকারীরা সাধারণত সময়ের মাত্রার উপর ভিত্তি করে পার্টিশন তৈরি করে। এখানে টেবিল তৈরি করুন বিবৃতির একটি উদাহরণ:
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) প্রতি মাসে ম্যানুয়ালি একটি নতুন পার্টিশন যোগ করতে হবে এবং নিয়মিতভাবে টেবিল স্কিমা বজায় রাখতে হবে। রিয়েল-টাইম ডেটা প্রসেসিংয়ের ক্ষেত্রে কল্পনা করুন, যেখানে আপনাকে প্রতিদিন বা এমনকি প্রতি ঘন্টায় পার্টিশন তৈরি করতে হতে পারে, ম্যানুয়ালি এটি করা দীর্ঘ পছন্দ নয়। এজন্য আমরা ডাইনামিক পার্টিশন চালু করেছি।
ডাইনামিক পার্টিশনের মাধ্যমে, ডরিস স্বয়ংক্রিয়ভাবে ডেটা পার্টিশন তৈরি করে এবং পুনরুদ্ধার করে যতক্ষণ না ব্যবহারকারী পার্টিশন ইউনিট, ঐতিহাসিক পার্টিশনের সংখ্যা এবং ভবিষ্যতের পার্টিশনের সংখ্যা উল্লেখ করে। এই কার্যকারিতা ডরিস ফ্রন্টেন্ডে একটি নির্দিষ্ট থ্রেডের উপর নির্ভর করে। এটি ক্রমাগত ভোট দেয় এবং নতুন পার্টিশন তৈরি করার জন্য বা পুরানো পার্টিশনগুলি পুনরুদ্ধার করার জন্য পরীক্ষা করে এবং টেবিলের পার্টিশন স্কিমা আপডেট করে।
এটি একটি টেবিলের জন্য একটি উদাহরণ তৈরি করুন টেবিল বিবৃতি যা দিনে বিভাজিত হয়। 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
মান ডায়াল করতে হবে এবং এটি ক্লাস্টারে অপ্রয়োজনীয় মেটাডেটা ওভারহেডের দিকে নিয়ে যেতে পারে।
অতএব, ডায়নামিক পার্টিশন প্রয়োগ করার সময়, মেটাডেটা পরিচালনার সুবিধা এবং দক্ষতার মধ্যে একটি ট্রেড-অফ রয়েছে।
ব্যবসার জটিলতা বাড়ার সাথে সাথে ডায়নামিক পার্টিশন অপর্যাপ্ত হয়ে যায় কারণ:
এই কার্যকরী সীমাবদ্ধতার পরিপ্রেক্ষিতে, আমরা একটি নতুন পার্টিশন পদ্ধতির পরিকল্পনা করতে শুরু করেছি যা পার্টিশন ব্যবস্থাপনাকে স্বয়ংক্রিয় করতে এবং ডেটা টেবিল রক্ষণাবেক্ষণকে সহজ করতে পারে।
আমরা খুঁজে বের করেছি যে আদর্শ পার্টিশন বাস্তবায়ন করা উচিত:
আগেরটি স্বয়ংক্রিয়তা এবং পরেরটি নমনীয়তার জন্য। তাদের উভয়কে উপলব্ধি করার সারমর্ম হল পার্টিশন তৈরিকে প্রকৃত ডেটার সাথে যুক্ত করা।
তারপরে আমরা নিম্নলিখিতগুলি সম্পর্কে চিন্তা করতে শুরু করি: টেবিল তৈরির সময় বা নিয়মিত পোলিং এর মাধ্যমে না করে যদি আমরা ডেটা ইনজেস্ট না হওয়া পর্যন্ত পার্টিশন তৈরি করা বন্ধ রাখি? পার্টিশন ডিস্ট্রিবিউশন পূর্ব-নির্মাণের পরিবর্তে, আমরা "ডেটা-টু-পার্টিশন" ম্যাপিং নিয়মগুলি সংজ্ঞায়িত করতে পারি যাতে ডেটা আসার পরে পার্টিশনগুলি তৈরি করা হয়।
ম্যানুয়াল পার্টিশনের তুলনায়, এই পুরো প্রক্রিয়াটি সম্পূর্ণরূপে স্বয়ংক্রিয় হবে, মানুষের রক্ষণাবেক্ষণের প্রয়োজনীয়তা দূর করবে। ডায়নামিক পার্টিশনের তুলনায়, এটি ব্যবহার করা হয় না এমন পার্টিশন বা প্রয়োজনীয় পার্টিশন থাকা এড়িয়ে যায় কিন্তু উপস্থিত নেই।
এর সাথে, আমরা উপরোক্ত পরিকল্পনাটি বাস্তবায়িত করি। ডেটা ইনজেশনের সময়, ডরিস কনফিগার করা নিয়মের উপর ভিত্তি করে ডেটা পার্টিশন তৈরি করে। ডাটা প্রসেসিং এবং ডিস্ট্রিবিউশনের জন্য দায়ী ডরিস ব্যাকএন্ড নোডগুলি এক্সিকিউশন প্ল্যানের ডেটাসিঙ্ক অপারেটরে ডেটার প্রতিটি সারির জন্য উপযুক্ত পার্টিশন খুঁজে বের করার চেষ্টা করবে। এটি আর এমন ডেটা ফিল্টার করে না যা বিদ্যমান কোনো পার্টিশনের সাথে খাপ খায় না বা এই ধরনের পরিস্থিতির জন্য একটি ত্রুটি রিপোর্ট করে কিন্তু স্বয়ংক্রিয়ভাবে সমস্ত ইনজেস্টেড ডেটার জন্য পার্টিশন তৈরি করে।
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 | p200 | 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)
NULL পার্টিশন
তালিকা দ্বারা স্বয়ংক্রিয় বিভাজন সহ, ডরিস 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 সীমানা সঠিকভাবে উদ্দিষ্ট ব্যবসার যুক্তি উপস্থাপন করতে পারে না।
স্বয়ংক্রিয় পার্টিশন ডায়নামিক পার্টিশনের বেশিরভাগ ক্ষেত্রেই কভার করে, যেখানে আপফ্রন্ট পার্টিশন নিয়মের সংজ্ঞার সুবিধা চালু করা হয়। নিয়মগুলি একবার সংজ্ঞায়িত হয়ে গেলে, পার্টিশন তৈরির কাজগুলির বেশিরভাগই ডিবিএর পরিবর্তে ডরিস দ্বারা স্বয়ংক্রিয়ভাবে পরিচালনা করা হয়।
অটো পার্টিশন ব্যবহার করার আগে, প্রাসঙ্গিক সীমাবদ্ধতাগুলি বোঝা গুরুত্বপূর্ণ:
LIST দ্বারা স্বয়ংক্রিয় বিভাজন একাধিক কলামের উপর ভিত্তি করে বিভাজন সমর্থন করে, কিন্তু প্রতিটি স্বয়ংক্রিয়ভাবে তৈরি করা পার্টিশনে শুধুমাত্র একটি একক মান থাকে এবং পার্টিশনের নামের দৈর্ঘ্য 50 অক্ষরের বেশি হতে পারে না। মনে রাখবেন যে পার্টিশনের নামগুলি নির্দিষ্ট নামকরণের নিয়ম অনুসরণ করে, যার মেটাডেটা পরিচালনার জন্য বিশেষ প্রভাব রয়েছে। তার মানে 50-অক্ষরের সমস্ত জায়গা ব্যবহারকারীর হাতে নেই।
RANGE দ্বারা স্বয়ংক্রিয় বিভাজন শুধুমাত্র একটি একক পার্টিশন কলাম সমর্থন করে, যা DATE বা DATETIME প্রকারের হতে হবে।
তালিকা দ্বারা স্বয়ংক্রিয় বিভাজন শূন্য পার্টিশন কলাম এবং শূন্য মান সন্নিবেশ সমর্থন করে। RANGE দ্বারা স্বয়ংক্রিয় বিভাজন NULLABLE পার্টিশন কলাম সমর্থন করে না।
Apache Doris 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% এর কাছাকাছি পৌঁছেছিল।
এই পরীক্ষার ফলাফলের উপসংহারে, ডেটা ইনজেশন কর্মক্ষমতার উপর স্বয়ংক্রিয় পার্টিশন সক্রিয় করার প্রভাব ন্যূনতম।
Apache Doris 2.1.0 থেকে স্বয়ংক্রিয় পার্টিশন DDL এবং পার্টিশন পরিচালনাকে সরল করেছে। এটি বৃহৎ আকারের ডেটা প্রক্রিয়াকরণে উপযোগী এবং ব্যবহারকারীদের জন্য অন্যান্য ডাটাবেস সিস্টেম থেকে Apache Doris-এ স্থানান্তর করা সহজ করে তোলে।
অধিকন্তু, আমরা আরও জটিল ডেটা টাইপ সমর্থন করার জন্য স্বয়ংক্রিয় পার্টিশনের ক্ষমতা প্রসারিত করতে প্রতিশ্রুতিবদ্ধ।
RANGE দ্বারা স্বয়ংক্রিয় বিভাজনের পরিকল্পনা:
সাংখ্যিক মান সমর্থন;
ব্যবহারকারীদের পার্টিশন পরিসরের বাম এবং ডান সীমানা নির্দিষ্ট করার অনুমতি দেয়।
তালিকা দ্বারা স্বয়ংক্রিয় বিভাজনের পরিকল্পনা: