paint-brush
Apache Doris'te Veri Parçalamanın Otomasyona ve Esnekliğe Doğru Evrimiile@frankzzz
Yeni tarih

Apache Doris'te Veri Parçalamanın Otomasyona ve Esnekliğe Doğru Evrimi

ile Frank Z29m2024/07/20
Read on Terminal Reader

Çok uzun; Okumak

Apache Doris, V2.1.0'da Otomatik Bölümlemeyi sunuyor. Apache Doris 2.1.0'dan bu yana DDL ve bölüm yönetimini basitleştirdi. Büyük ölçekli veri işlemede kullanışlıdır ve kullanıcıların diğer veritabanı sistemlerinden Apache Doris'e geçişini kolaylaştırır.
featured image - Apache Doris'te Veri Parçalamanın Otomasyona ve Esnekliğe Doğru Evrimi
Frank Z HackerNoon profile picture


Büyük veri kümelerini yönetmek için dağıtılmış veritabanları bölümleme ve gruplama gibi stratejiler sunar. Veriler belirli kurallara göre daha küçük birimlere bölünür ve farklı düğümlere dağıtılır, böylece veritabanları daha yüksek performans ve veri yönetimi esnekliği için paralel işleme gerçekleştirebilir.


Birçok veritabanında olduğu gibi Apache Doris de verileri bölümlere ayırır ve ardından bölüm daha sonra bölümlere ayrılır. Bölümler tipik olarak zamana veya diğer sürekli değerlere göre tanımlanır. Bu, sorgu motorlarının, ilgisiz veri aralıklarını budayarak sorgular sırasında hedef verileri hızlı bir şekilde bulmasına olanak tanır.


Paketleme ise verileri bir veya daha fazla sütunun karma değerlerine göre dağıtarak veri çarpıklığını önler.


Sürüm 2.1.0'dan önce Apache Doris'te veri bölümleri oluşturmanın iki yolu vardı:


  • Manuel Bölümleme : Kullanıcılar, bölümleri tablo oluşturma ifadesinde belirtir veya daha sonra DDL ifadeleri aracılığıyla değiştirir.


  • Dinamik Bölüm : Sistem, veri alım süresine bağlı olarak önceden tanımlanmış bir aralıktaki bölümleri otomatik olarak korur.


Apache Doris 2.1.0'da Otomatik Bölümlemeyi tanıttık. Verilerin ARALIK veya LİSTE'ye göre bölümlenmesini destekler ve otomatik bölümlendirmenin yanı sıra esnekliği daha da artırır.

Doris'te bölümleme stratejilerinin gelişimi

Veri dağıtımının tasarımında bölümleme planlamasına daha çok odaklanıyoruz çünkü bölümleme sütunlarının ve bölümleme aralıklarının seçimi büyük ölçüde gerçek veri dağıtım modellerine bağlıdır ve iyi bir bölümleme tasarımı tablonun sorgusunu ve depolama verimliliğini büyük ölçüde geliştirebilir.


Doris'te veri tablosu hiyerarşik bir şekilde bölümlere ve ardından paketlere bölünür. Aynı klasördeki veriler daha sonra veri çoğaltma, kümeler arası veri planlama ve yük dengeleme için Doris'teki minimum fiziksel depolama birimi olan bir veri tableti oluşturur.


Manuel Bölümleme

Doris, kullanıcıların ARALIK ve LİSTE'ye göre manuel olarak veri bölümleri oluşturmasına olanak tanır.


Günlükler ve işlem kayıtları gibi zaman damgalı veriler için kullanıcılar genellikle zaman boyutunu temel alan bölümler oluşturur. İşte CREATE TABLE ifadesinin bir örneği:


 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" );


Tablo, veri içe aktarma date göre bölümlendirilmiştir ve 4 bölüm önceden oluşturulmuştur. Her bölüm içinde veriler, user_id karma değerine bağlı olarak 16 bölüme daha bölünür.


Bu bölümleme ve gruplama tasarımıyla, 2018'den itibaren verileri sorgularken sistemin yalnızca p2018 bölümünü taraması gerekir. SQL sorgusu şöyle görünür:


 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 | | | +--------------------------------------------------------------------------------------+


Veriler bölümler arasında eşit olmayan bir şekilde dağıtılırsa karma tabanlı gruplandırma mekanizması, user_id değerine göre verileri daha da bölebilir. Bu, sorgulama ve depolama sırasında bazı makinelerde yük dengesizliğinin önlenmesine yardımcı olur.


Ancak gerçek dünyadaki iş senaryolarında, bir kümede onbinlerce tablo bulunabilir, bu da bunları manuel olarak yönetmenin imkansız olduğu anlamına gelir.


 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 ( ...... );


Yukarıdaki örnekte veriler aylık olarak bölümlendirilmiştir. Bu, veritabanı yöneticisinin (DBA) her ay manuel olarak yeni bir bölüm eklemesini ve tablo şemasını düzenli olarak korumasını gerektirir. Günlük, hatta saatlik bölümler oluşturmanız gerekebilecek gerçek zamanlı veri işleme durumunu düşünün; bunu manuel olarak yapmak artık bir seçenek değil. Bu yüzden Dinamik Bölüm'ü tanıttık.

Dinamik Bölüm

Dinamik Bölümleme sayesinde Doris, kullanıcı bölüm birimini, geçmiş bölümlerin sayısını ve gelecekteki bölümlerin sayısını belirttiği sürece veri bölümlerini otomatik olarak oluşturur ve geri alır. Bu işlevsellik, Doris Ön Uç'taki sabit bir iş parçacığına dayanır. Oluşturulacak yeni bölümleri veya geri alınacak eski bölümleri sürekli olarak yoklar ve kontrol eder ve tablonun bölüm şemasını günceller.


Bu, güne göre bölümlenmiş bir tablo için örnek bir CREATE TABLE ifadesidir. start ve end parametreleri sırasıyla -7 ve 3 olarak ayarlanmıştır; bu, sonraki 3 güne ait veri bölümlerinin önceden oluşturulacağı ve 7 günden daha eski olan geçmiş bölümlerin geri alınacağı anlamına gelir.


 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" );


Zamanla tablo her zaman [current date - 7, current date + 3] aralığındaki bölümleri koruyacaktır. Dinamik Bölümleme, ODS (Operasyonel Veri Deposu) katmanının doğrudan Kafka gibi harici kaynaklardan veri alması gibi gerçek zamanlı veri alımı senaryoları için özellikle kullanışlıdır.


start ve end parametreleri, bölümler için sabit bir aralık tanımlar ve kullanıcının yalnızca bu aralıktaki bölümleri yönetmesine olanak tanır. Ancak kullanıcının daha fazla geçmiş veri eklemesi gerekiyorsa start değerini çevirmesi gerekir ve bu da kümede gereksiz meta veri yüküne yol açabilir.


Bu nedenle Dinamik Bölüm uygulanırken meta veri yönetiminin rahatlığı ve verimliliği arasında bir denge vardır.

Geliştiricilerin sözleri

İşin karmaşıklığı arttıkça Dinamik Bölümleme yetersiz hale gelir çünkü:


  • Yalnızca RANGE'a göre bölümlemeyi destekler, LIST'e göre bölümlendirmeyi desteklemez.
  • Yalnızca mevcut gerçek dünya zaman damgalarına uygulanabilir.
  • Yalnızca tek bir sürekli bölüm aralığını destekler ve bu aralığın dışındaki bölümleri barındıramaz.


Bu işlevsel sınırlamalar göz önüne alındığında, hem bölüm yönetimini otomatikleştirebilecek hem de veri tablosu bakımını basitleştirebilecek yeni bir bölümleme mekanizması planlamaya başladık.


İdeal bölümleme uygulamasının şunları yapması gerektiğini anladık:


  • Tablo oluşturulduktan sonra bölümleri manuel olarak oluşturma ihtiyacını ortadan kaldırın;
  • Alınan tüm verileri ilgili bölümlere yerleştirebilme.


Birincisi otomasyonu, ikincisi ise esnekliği temsil eder. Her ikisini de gerçekleştirmenin özü, bölüm oluşturmayı gerçek verilerle ilişkilendirmektir.


Daha sonra şunu düşünmeye başladık: Tablo oluşturma sırasında veya düzenli yoklama yoluyla bölüm oluşturmak yerine, veriler alınana kadar bölüm oluşturmayı ertelersek ne olur? Bölüm dağıtımını önceden oluşturmak yerine, "veriden bölüme" eşleme kurallarını tanımlayabiliriz, böylece bölümler veri geldikten sonra oluşturulur.


Manuel Bölümleme ile karşılaştırıldığında, tüm bu süreç tamamen otomatik hale getirilecek ve insan bakımına duyulan ihtiyaç ortadan kalkacaktır. Dinamik Bölüm ile karşılaştırıldığında, kullanılmayan bölümlerin veya ihtiyaç duyulan ancak mevcut olmayan bölümlerin olmasını önler.

Otomatik Bölümleme

Apache Doris 2.1.0 ile yukarıdaki planı hayata geçiriyoruz. Veri alımı sırasında Doris, yapılandırılmış kurallara göre veri bölümleri oluşturur. Veri işleme ve dağıtımdan sorumlu Doris Arka Uç düğümleri, yürütme planının DataSink operatöründeki her veri satırı için uygun bölümü bulmaya çalışacaktır. Artık mevcut herhangi bir bölüme sığmayan verileri filtrelemez veya böyle bir durum için hata bildirmez; alınan tüm veriler için otomatik olarak bölümler oluşturur.

RANGE'a göre Otomatik Bölümleme

RANGE'e göre Otomatik Bölümleme, zaman boyutuna dayalı olarak optimize edilmiş bir bölümleme çözümü sağlar. Parametre konfigürasyonu açısından Dynamic Partition'a göre daha esnektir. Bunun sözdizimi aşağıdaki gibidir:


 AUTO PARTITION BY RANGE (FUNC_CALL_EXPR) () FUNC_CALL_EXPR ::= DATE_TRUNC ( <partition_column>, '<interval>' )


Yukarıdaki <partition_column> bölümleme sütunudur (yani bölümlemenin temel aldığı sütun). <interval> her bölümün istenen genişliği olan bölüm birimini belirtir.


Örneğin, bölüm sütunu k0 ise ve aya göre bölümlemek istiyorsanız, bölüm ifadesi AUTO PARTITION BY RANGE (DATE_TRUNC(k0, 'month')) olacaktır. İçe aktarılan tüm veriler için sistem, bölümün sol uç noktasını hesaplamak için DATE_TRUNC(k0, 'month') işlevini çağıracak ve ardından bir interval ekleyerek sağ uç noktasını hesaplayacaktır.


Artık Dinamik Bölümleme ile ilgili önceki bölümde tanıtılan DAILY_TRADE_VALUE tablosuna Otomatik Bölümleme uygulayabiliriz.


 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 ( ...... );


Bazı verileri içe aktardıktan sonra elde ettiğimiz bölümler şunlardır:


 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)


Gösterildiği gibi, içe aktarılan veriler için bölümler otomatik olarak oluşturulur ve mevcut verilerin aralığının ötesinde bölümler oluşturmaz.

LİSTE'ye Göre Otomatik Bölümleme

LIST'e Göre Otomatik Bölümleme, verileri region ve department gibi zamana bağlı olmayan boyutlara dayalı olarak parçalamak içindir. LIST ile veri bölümlemeyi desteklemeyen Dinamik Bölüm için bu boşluğu doldurur.


RANGE'e göre Otomatik Bölümleme, zaman boyutuna dayalı olarak optimize edilmiş bir bölümleme çözümü sağlar. Parametre konfigürasyonu açısından Dynamic Partition'a göre daha esnektir. Bunun sözdizimi aşağıdaki gibidir:


 AUTO PARTITION BY LIST (`partition_col`) ()


Bu, bölüm sütunu olarak city kullanıldığı LIST'e göre Otomatik Bölümleme örneğidir:


 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)


Denver, Boston ve Los Angeles şehirleri için veriler girildikten sonra sistem, şehir adlarına göre otomatik olarak ilgili bölümleri oluşturdu. Önceden, bu tür özel bölümleme yalnızca manuel DDL ifadeleriyle gerçekleştirilebiliyordu. LIST ile Otomatik Bölümleme veritabanı bakımını bu şekilde basitleştirir.

İpuçları ve notlar

Geçmiş bölümleri manuel olarak ayarlayın

Otomatik Bölümleme, geçmiş bölümleri otomatik olarak geri almadığından, hem gerçek zamanlı verileri hem de ara sıra geçmiş güncellemeleri alan tablolar için iki seçenek öneririz:


  • Ara sıra gerçekleşen geçmiş veri güncellemeleri için otomatik olarak bölümler oluşturacak Otomatik Bölümlendirmeyi kullanın.

  • Otomatik Bölümlemeyi kullanın ve geçmiş güncellemeleri karşılamak için manuel olarak bir LESS THAN bölümü oluşturun. Bu, geçmiş ve gerçek zamanlı verilerin daha net bir şekilde ayrılmasına olanak tanır ve veri yönetimini kolaylaştırır.


 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)


BOŞ bölüm

LIST'e Göre Otomatik Bölümleme ile Doris, NULL değerlerinin NULL bölümlerde saklanmasını destekler. Örneğin:


 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)


Bununla birlikte, ARALIK'a Göre Otomatik Bölümleme NULL bölümlerini desteklemez çünkü NULL değerleri en küçük LESS THAN bölümünde depolanır ve bunun için uygun aralığı güvenilir bir şekilde belirlemek imkansızdır. Otomatik Bölümleme (-INFINITY, MIN_VALUE) aralığına sahip bir NULL bölüm oluştursaydı, MIN_VALUE sınırı amaçlanan iş mantığını doğru şekilde temsil etmeyebileceğinden bu bölümün üretim sırasında yanlışlıkla silinmesi riski olurdu.

Özet

Otomatik Bölümleme, Dinamik Bölümlemenin kullanım durumlarının çoğunu kapsarken, ön bölümleme kuralı tanımının yararını da sunar. Kurallar tanımlandıktan sonra, bölüm oluşturma işinin büyük kısmı otomatik olarak DBA yerine Doris tarafından gerçekleştirilir.


Otomatik Bölümlemeyi kullanmadan önce ilgili sınırlamaları anlamak önemlidir:


  1. LIST'e Göre Otomatik Bölümleme, birden çok sütuna dayalı bölümlemeyi destekler, ancak otomatik olarak oluşturulan her bölüm yalnızca tek bir değer içerir ve bölüm adının uzunluğu 50 karakteri aşamaz. Bölüm adlarının, meta veri yönetimi için özel etkileri olan belirli adlandırma kurallarına uyduğunu unutmayın. Bu, 50 karakterlik alanın tamamının kullanıcının kullanımında olmadığı anlamına gelir.


  2. ARALIK'a göre Otomatik Bölümleme yalnızca DATE veya DATETIME türünde olması gereken tek bir bölüm sütununu destekler.


  3. LIST'e göre Otomatik Bölümleme, NULLABLE bölüm sütununu ve NULL değerlerinin eklenmesini destekler. ARALIK'a göre Otomatik Bölümleme, NULLABLE bölümleme sütununu desteklemez.


  4. Apache Doris 2.1.3'ten sonra Otomatik Bölümlemenin Dinamik Bölümleme ile birlikte kullanılması önerilmez.

Performans karşılaştırması

Otomatik Bölümleme ve Dinamik Bölümleme arasındaki ana işlevsel farklar, bölüm oluşturma ve silme, desteklenen bölüm türleri ve bunların içe aktarma performansı üzerindeki etkisinde yatmaktadır.


Dinamik Bölüm, bölümleri düzenli aralıklarla oluşturmak ve geri almak için sabit iş parçacıklarını kullanır. Yalnızca RANGE'a göre bölümlendirmeyi destekler. Buna karşılık, Otomatik Bölümleme hem RANGE hem de LIST'e göre bölümlemeyi destekler. Veri alımı sırasında belirli kurallara göre isteğe bağlı olarak otomatik olarak bölümler oluşturarak daha yüksek düzeyde otomasyon ve esneklik sağlar.


Dinamik Bölüm, veri alma hızını yavaşlatmaz; Otomatik Bölümleme ise öncelikle mevcut bölümleri kontrol edip ardından isteğe bağlı olarak yeni bölümler oluşturduğu için belirli zaman ek yüklerine neden olur. Performans testi sonuçlarını sunacağız.



Otomatik Bölümleme: besleme iş akışı

Bu bölüm, Otomatik Bölümleme mekanizmasıyla veri alımının nasıl uygulandığıyla ilgilidir ve örnek olarak Akış Yüklemesini kullanıyoruz. Doris bir veri içe aktarma işlemini başlattığında Doris Arka Uç düğümlerinden biri Koordinatör rolünü üstlenir. İlk veri işleme çalışmasından ve ardından verilerin yürütme için Yürütücüler olarak bilinen uygun BE düğümlerine gönderilmesinden sorumludur.



Koordinatörün yürütme hattının son Veri Alıcı Düğümünde, verilerin başarılı bir şekilde iletilebilmesi ve saklanabilmesi için önce doğru bölümlere, klasörlere ve Doris Arka Uç düğüm konumlarına yönlendirilmesi gerekir.


Bu veri aktarımını sağlamak için Koordinatör ve Yürütücü düğümleri iletişim kanalları oluşturur:


  • Gönderen uca Düğüm Kanalı denir.
  • Alıcı uca Tablet Kanalı denir.


Veriler için doğru bölümlerin belirlenmesi sürecinde Otomatik Bölümleme şu şekilde devreye girer:



Önceden, Otomatik Bölümleme olmadan, bir tablo gerekli bölüme sahip olmadığında Doris'teki davranış, BE düğümlerinin bir DATA_QUALITY_ERROR raporlanana kadar hataları biriktirmesi yönündeydi. Artık Otomatik Bölümleme etkinleştirildiğinde, gerekli bölümü anında oluşturmak için Doris Frontend'e bir istek başlatılacaktır. Bölüm oluşturma işlemi tamamlandıktan sonra Doris Frontend, Koordinatöre yanıt verir ve ardından veri alma sürecine devam etmek için ilgili iletişim kanallarını (Düğüm Kanalı ve Tablet Kanalı) açar. Bu, kullanıcılar için kusursuz bir deneyimdir.


Gerçek dünyadaki bir küme ortamında, Koordinatörün Doris Frontend'in bölüm oluşturmayı tamamlamasını beklerken harcadığı zaman büyük masraflara neden olabilir. Bunun nedeni, Thrift RPC çağrılarının doğal gecikmesinin yanı sıra, yüksek yük koşulları altında Ön Uçtaki kilit çekişmesidir.


Otomatik Bölümlemede veri alımı verimliliğini artırmak için Doris, FE'ye yapılan RPC çağrılarının sayısını büyük ölçüde azaltmak amacıyla toplu işlem uyguladı. Bu, veri yazma işlemleri için dikkate değer bir performans artışı sağlar.


FE Master bölüm oluşturma işlemini tamamladığında yeni bölümün hemen görünür hale geleceğini unutmayın. Ancak içe aktarma işlemi sonuçta başarısız olursa veya iptal edilirse oluşturulan bölümler otomatik olarak geri alınmaz.

Otomatik Bölümleme performansı

Farklı kullanım durumlarını kapsayacak şekilde Doris'te Otomatik Bölümleme'nin performansını ve kararlılığını test ettik:


Durum 1 : 1 Ön Uç + 3 Arka Uç; Her biri 100 milyon satır ve 2.000 bölümden oluşan, rastgele oluşturulmuş 6 veri kümesi; 6 veri kümesini aynı anda 6 tabloya aktardı


  • Amaç : Yüksek basınç altında Otomatik Bölümleme performansını değerlendirin ve herhangi bir performans düşüşü olup olmadığını kontrol edin.


  • Sonuçlar : Otomatik Bölümleme, tüm içe aktarma işlemlerinin istikrarlı bir şekilde çalışmasıyla birlikte ortalama %5'in altında bir performans kaybı sağlar.



Durum 2 : 1 Ön Uç + 3 Arka Uç; Rutin Yüke göre Flink'ten saniyede 100 satırın alınması; sırasıyla 1, 10 ve 20 eşzamanlı işlem (tablo) ile test etme


  • Amaç : Otomatik Bölümleme ile farklı eşzamanlılık düzeyleri altında ortaya çıkabilecek olası veri biriktirme listesi sorunlarını belirlemek.


  • Sonuçlar : Otomatik Bölümleme etkin olsun ya da olmasın, CPU kullanımı %100'e yaklaştığında 20 eş zamanlı işlemde bile test edilen tüm eşzamanlılık düzeylerinde herhangi bir geri basınç sorunu olmadan veri alımı başarılı oldu.



Bu testlerin sonuçlarına göre Otomatik Bölümlemeyi etkinleştirmenin veri alımı performansı üzerindeki etkisi minimum düzeydedir.

Sonuç ve Gelecek Planları

Otomatik Bölümleme, Apache Doris 2.1.0'dan bu yana DDL ve bölüm yönetimini basitleştirdi. Büyük ölçekli veri işlemede kullanışlıdır ve kullanıcıların diğer veritabanı sistemlerinden Apache Doris'e geçişini kolaylaştırır.


Ayrıca, Otomatik Bölümlemenin yeteneklerini daha karmaşık veri türlerini destekleyecek şekilde genişletmeye kararlıyız.


ARALIK'a göre Otomatik Bölümleme Planları:


  • Sayısal değerleri destekleyin;


  • Kullanıcıların bölüm aralığının sol ve sağ sınırlarını belirlemesine olanak tanır.


LİSTE'ye Göre Otomatik Bölümleme Planları:


  • Belirli kurallara göre birden fazla değerin aynı bölümde birleştirilmesine izin verin.