湖倉一體之前,數據分析經歷了數據庫、數據倉庫和數據湖分析三個時代。
-
首先是數據庫,它是一個最基礎的概念,主要負責聯機事務處理,也提供基本的數據分析能力。
-
隨著數據量的增長,出現了數據倉庫,它存儲的是經過清洗、加工以及建模后的高價值的數據,供業務人員進行數據分析。
-
數據湖的出現,主要是為了去滿足企業對原始數據的存儲、管理和再加工的需求。這里的需求主要包括兩部分,首先要有一個低成本的存儲,用于存儲結構化、半結構化,甚至非結構化的數據;另外,就是希望有一套包括數據處理、數據管理以及數據治理在內的一體化解決方案。
數據倉庫解決了數據快速分析的需求,數據湖解決了數據的存儲和管理的需求,而湖倉一體要解決的就是如何讓數據能夠在數據湖和數據倉庫之間進行無縫的集成和自由的流轉,從而幫助用戶直接利用數據倉庫的能力來解決數據湖中的數據分析問題,同時又能充分利用數據湖的數據管理能力來提升數據的價值。
適用場景?
Doris 在設計湖倉一體時,主要考慮如下四個應用場景:
-
湖倉查詢加速:Doris 作為一個非常高效的 OLAP 查詢引擎,有著非常好的 MPP 向量化的分布式的查詢層,可以直接利用 Doris 非常高效的查詢引擎,對湖上數據進行加速分析。
-
統一數據分析網關:提供各類異構數據源的查詢和寫入能力,支持用戶將這些外部數據源統一到 Doris 的元數據映射結構上,當用戶通過 Doris 查詢這些外部數據源時,能夠提供一致的查詢體驗。
-
統一數據集成:首先通過數據湖的數據源連接能力,能夠讓多數據源的數據以增量或全量的方式同步到 Doris,并且利用 Doris 的數據處理能力對這些數據進行加工。加工完的數據一方面可以直接通過 Doris 對外提供查詢,另一方面也可以通過 Doris 的數據導出能力,繼續為下游提供全量或增量數據服務。通過 Doris 可以減少對外部工具的依賴,可以直接將上下游數據,以及包括同步、加工、處理在內的整條鏈路打通。
-
更加開放的數據平臺:眾多數據倉庫有著各自的存儲格式,用戶如果想要使用一個數據倉庫,第一步就需要把外部數據通過某種方式導入到數據倉庫中才能進行查詢。這樣就是一個比較封閉的生態,數據倉庫中數據除了數倉自己本身可以查詢以外,其它外部工具是無法進行直接訪問的。一些企業在使用包括 Doris 在內的一些數倉產品的時候就會有一些顧慮,比如數據是否會被鎖定到某一個數據倉庫里,是否還有便捷的方式進行導出。通過湖倉一體生態的接入,可以用更加開放的數據格式來管理數據,比如可以用 Parquet/ORC 格式來去存儲數據,這樣開放開源的數據格式可以被很多外部系統去訪問。另外,Iceberg,Hudi 等都提供了開放式的元數據管理能力,不管元數據是存儲在 Doris 本身,還是存儲在 Hive Meta store,或者存儲在其它統一元數據中心,都可以通過一些對外公開的 API 對這些數據進行管理。通過更加開放的數據生態,可以幫助企業更快地接入一個新的數據管理系統,降低企業數據遷移的成本和風險。
基于 Doris 的湖倉一體架構?
Doris 通過多源數據目錄(Multi-Catalog)功能,支持了包括 Apache Hive、Apache Iceberg、Apache Hudi、Apache Paimon、LakeSoul、Elasticsearch、MySQL、Oracle、SQL Server 等主流數據湖、數據庫的連接訪問。以及可以通過 Apache Ranger 等進行統一的權限管理,具體架構如下:
其數據湖的主要對接流程為:
-
創建元數據映射:Doris 通過 Catalog 獲取數據湖元數據并緩存在 Doris 中,用于數據湖元數據的管理。在元數據映射過程中 Doris 除了支持傳統 JDBC 的用戶名密碼認證外,還支持基于 Kerberos 和 Ranger 的權限認證,基于 KMS 的數據加密。
-
發起查詢操作:當用戶從 FE 發起數據湖查詢時,Doris 使用自身存儲的數據湖元數生成造查詢計劃,利用 Native 的 Reader 組件從外部存儲(HDFS、S3)上獲取數據進行數據計算和分析。在數據查詢過程中 Doris 會將數據湖熱點數據緩存在本地,當下次相同查詢到來時數據緩存能很好起到查詢加速的效果。
-
結果返回:當查詢完成后將查詢結果通過 FE 返回給用戶。
-
計算結果入湖:當用戶并不想將計算結果返回,而是需要將計算結果進一步寫入數據湖時可以通過 export 的方式以標準數據格式(CSV、Parquet、ORC)將數據寫回數據湖。
核心技術?
在多源數據連接上 Doris 通過可擴展連接器讀取外部數據。同時通過元數據緩存、數據緩存、Native Reader、IO 優化、統計信息優化等一些措施,極大加速了數據湖分析能力。
可擴展的連接框架?
在數據的對接中包括元數據的對接和數據的讀取。
-
元數據對接:元數據對接在 FE 完成,通過 FE 的 MetaData 管理器來實現基于 HiveMetastore、JDBC 和文件的元數據對接和管理工作。
-
數據讀取:通過 NativeReader 可以高效的讀取存放在 HDFS、對象存儲上的 Parquet、ORC、Text 格式數據。也可以通過 JniConnector 對接 Java 大數據生態。
高效緩存策略?
Doris 通過元數據緩存、數據緩存和查詢結果緩存來提升查詢性能。
元數據緩存
Doris 提供了手動同步元數據、定期自動同步元數據、元數據訂閱(只支持 HiveMetastore)三種方式來同步數據湖的元數據信息到 Doris,并將元數據存儲在 Doris 的 FE 的內存中。當用戶發起查詢后 Doris 直接從內存中獲取元數據并快速生成查詢規劃。保障了元數據的實時和高效。在元數據同步上 Doris 通過并發的元數據事件合并實現高效的元數據同步,其每秒可以處理 100 個以上的元數據事件。
高效的數據緩存
-
文件緩存:Doris 通過將數據湖中的熱點數據存儲在本地磁盤上,減少數據掃描過程中網絡數據的傳輸,提高數據訪問的性能。
-
緩存分布策略:在數據緩存中 Doris 通過一致性哈希將數據分布在各個 BE 節點上,盡量避免節點擴縮容帶來的緩存失效問題。
-
緩存淘汰(更新)策略:同時當 Doris 發現數據文件對應的元數據更新后,會及時淘汰緩存以保障數據的一致性。
查詢結果緩存和分區緩存
-
查詢結果緩存:Doris 根據 SQL 語句將之前查詢的結果緩存起來,當下次相同的查詢再次發起時可以直接從緩存中獲取數據返回到客戶端,極大的提高了查詢的效率和并發。
-
分區緩存:Doris 還支持將部分分區數據緩存在 BE 端提升查詢效率。比如查詢最近 7 天的數據,可以將前 6 天的計算后的緩存結果,和當天的事實計算結果進行合并,得到最終查詢結果,最大限度減少實時計算的數據量,提升查詢效率。
高效的 Native Reader?
-
自研 Native Reader 避免數據轉換:Doris 在數據分析時有其自身的列存方式,同時 Parquet、ORC 也有自身的列存格式。如果直接使用開源的 Parquet 或者 ORC Reader 的話就會存在一個 Doris 列存和 Parquet/ORC 列存的轉換過程。這樣的話就會多一次格式轉換的開銷,為了解決這個問題 我們自研了一套 Parquet/ORC NativeReader,直接讀取 Parquet、ORC 文件來提高查詢效率。
-
延遲物化:同時我們實現的 Native Reader 還能很好的利用智能索引和過濾器提高數據讀取效率。比如說在某些場景下我可能只針對 ID 列去做一個過濾。我們的優化做法是首先第一步我會把 ID 列單獨讀出來。然后在這一列上做完過濾以后,我會把這個過濾后的剩余下來的這個行號記錄下來。拿這個行號再去讀剩下兩列,這樣來進一步的減少數據掃描,加速文件的分析性能。
- 向量化讀取數據:同時在文件數據的讀取過程中我們引入向量化的方式讀取數據,極大加速了數據讀取效率。
Merge IO?
在網絡中難免會出現大量小文件的網絡 IO 請求取影響 IO 性能,在這種情況下我們采用 IO 合并去優化這種情況。
比如我們設置一個策略將小于 3MB 的 IO 請求合并(Merge IO)在一次請求中處理。那么之前可能是有 8 次的小的 IO 請求,我們可以把 8 次合并成 5 次 IO 請求去去讀取數據。這樣減少了網絡 IO 請求的速度,提高了網絡訪問數據的效率。
Merge IO 的確定是它可能會讀取一些不必要的數據,因為它把中間可能不必要讀取的數據合并起來一塊讀過來了。但是從整體的吞吐上來講其性能有很大的提高,在碎文件(比如:1KB - 1MB)較多的場景優化效果很明顯。同時我們通過控制 Merge IO 的大小來達到整體的平衡。
統計信息提高查詢規劃效果?
Doris 通過收集統計信息有助于優化器了解數據分布特性,在進行 CBO(基于成本優化)時優化器會利用這些統計信息來計算謂詞的選擇性,并估算每個執行計劃的成本。從而選擇更優的計劃以大幅提升查詢效率。在數據湖場景我們可以通過收集外表的統計信息來提升查詢規劃器的效果。
統計信息的收集方式包括手動收集和自動收集。
同時為了保證收集統計信息不會對 BE 產生壓力,我們支持了采樣收集統計信息。
在一些場景下用戶歷史數據可能很少查找,但是熱數據會被經常訪問,因此我們也提供了基于分區的統計信息收集在保障熱數據高效的查詢效率和統計信息收集對 BE 產生負載的中間取得平衡。
多源數據目錄?
多源數據目錄(Multi-Catalog)功能,旨在能夠更方便對接外部數據目錄,以增強 Doris 的數據湖分析和聯邦數據查詢能力。
在之前的 Doris 版本中,用戶數據只有兩個層級:Database 和 Table。當我們需要連接一個外部數據目錄時,我們只能在 Database 或 Table 層級進行對接。比如通過?create external table
?的方式創建一個外部數據目錄中的表的映射,或通過?create external database
?的方式映射一個外部數據目錄中的 Database。如果外部數據目錄中的 Database 或 Table 非常多,則需要用戶手動進行一一映射,使用體驗不佳。
而新的 Multi-Catalog 功能在原有的元數據層級上,新增一層 Catalog,構成 Catalog -> Database -> Table 的三層元數據層級。
該功能將作為之前外表連接方式(External Table)的補充和增強,幫助用戶進行快速的多數據目錄聯邦查詢。
基礎概念?
-
Internal Catalog
Doris 原有的 Database 和 Table 都將歸屬于 Internal Catalog。Internal Catalog 是內置的默認 Catalog,用戶不可修改或刪除。
-
External Catalog
可以通過?CREATE CATALOG?命令創建一個 External Catalog。創建后,可以通過?SHOW CATALOGS?命令查看已創建的 Catalog。
-
切換 Catalog
用戶登錄 Doris 后,默認進入 Internal Catalog,因此默認的使用和之前版本并無差別,可以直接使用?
SHOW DATABASES
,USE DB
?等命令查看和切換數據庫。用戶可以通過?SWITCH?命令切換 Catalog。如:
SWITCH internal; SWITCH hive_catalog;
切換后,可以直接通過?
SHOW DATABASES
,USE DB
?等命令查看和切換對應 Catalog 中的 Database。Doris 會自動通過 Catalog 中的 Database 和 Table。用戶可以像使用 Internal Catalog 一樣,對 External Catalog 中的數據進行查看和訪問。 -
刪除 Catalog
可以通過?DROP CATALOG?命令刪除一個 External Catalog,Internal Catalog 無法刪除。該操作僅會刪除 Doris 中該 Catalog 的映射信息,并不會修改或變更任何外部數據目錄的內容。
連接示例?
連接 Hive
這里我們通過連接一個 Hive 集群說明如何使用 Catalog 功能。
更多關于 Hive 的說明,請參閱:Hive Catalog
1. 創建 Catalog
CREATE CATALOG hive PROPERTIES ('type'='hms','hive.metastore.uris' = 'thrift://172.21.0.1:7004'
);
更多查看:CREATE CATALOG 語法幫助
2. 查看 Catalog
3. 創建后,可以通過?SHOW CATALOGS
?命令查看 catalog:
mysql> SHOW CATALOGS;
+-----------+-------------+----------+-----------+-------------------------+---------------------+------------------------+
| CatalogId | CatalogName | Type | IsCurrent | CreateTime | LastUpdateTime | Comment |
+-----------+-------------+----------+-----------+-------------------------+---------------------+------------------------+
| 10024 | hive | hms | yes | 2023-12-25 16:11:41.687 | 2023-12-25 20:43:18 | NULL |
| 0 | internal | internal | | UNRECORDED | NULL | Doris internal catalog |
+-----------+-------------+----------+-----------+-------------------------+---------------------+------------------------+
-
SHOW CATALOGS 語法幫助
-
可以通過?SHOW CREATE CATALOG?查看創建 Catalog 的語句。
-
可以通過?ALTER CATALOG?修改 Catalog 的屬性。
4. 切換 Catalog
通過?SWITCH
?命令切換到 hive catalog,并查看其中的數據庫:
mysql> SWITCH hive;
Query OK, 0 rows affected (0.00 sec)mysql> SHOW DATABASES;
+-----------+
| Database |
+-----------+
| default |
| random |
| ssb100 |
| tpch1 |
| tpch100 |
| tpch1_orc |
+-----------+
查看更多:SWITCH 語法幫助
5. 使用 Catalog
切換到 Catalog 后,則可以正常使用內部數據源的功能。
如切換到 tpch100 數據庫,并查看其中的表:
mysql> USE tpch100;
Database changedmysql> SHOW TABLES;
+-------------------+
| Tables_in_tpch100 |
+-------------------+
| customer |
| lineitem |
| nation |
| orders |
| part |
| partsupp |
| region |
| supplier |
+-------------------+
查看 lineitem 表的 schema:
mysql> DESC lineitem;
+-----------------+---------------+------+------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+------+---------+-------+
| l_shipdate | DATE | Yes | true | NULL | |
| l_orderkey | BIGINT | Yes | true | NULL | |
| l_linenumber | INT | Yes | true | NULL | |
| l_partkey | INT | Yes | true | NULL | |
| l_suppkey | INT | Yes | true | NULL | |
| l_quantity | DECIMAL(15,2) | Yes | true | NULL | |
| l_extendedprice | DECIMAL(15,2) | Yes | true | NULL | |
| l_discount | DECIMAL(15,2) | Yes | true | NULL | |
| l_tax | DECIMAL(15,2) | Yes | true | NULL | |
| l_returnflag | TEXT | Yes | true | NULL | |
| l_linestatus | TEXT | Yes | true | NULL | |
| l_commitdate | DATE | Yes | true | NULL | |
| l_receiptdate | DATE | Yes | true | NULL | |
| l_shipinstruct | TEXT | Yes | true | NULL | |
| l_shipmode | TEXT | Yes | true | NULL | |
| l_comment | TEXT | Yes | true | NULL | |
+-----------------+---------------+------+------+---------+-------+
查詢示例:
mysql> SELECT l_shipdate, l_orderkey, l_partkey FROM lineitem limit 10;
+------------+------------+-----------+
| l_shipdate | l_orderkey | l_partkey |
+------------+------------+-----------+
| 1998-01-21 | 66374304 | 270146 |
| 1997-11-17 | 66374304 | 340557 |
| 1997-06-17 | 66374400 | 6839498 |
| 1997-08-21 | 66374400 | 11436870 |
| 1997-08-07 | 66374400 | 19473325 |
| 1997-06-16 | 66374400 | 8157699 |
| 1998-09-21 | 66374496 | 19892278 |
| 1998-08-07 | 66374496 | 9509408 |
| 1998-10-27 | 66374496 | 4608731 |
| 1998-07-14 | 66374592 | 13555929 |
+------------+------------+-----------+
也可以和其他數據目錄中的表進行關聯查詢:
mysql> SELECT l.l_shipdate FROM hive.tpch100.lineitem l WHERE l.l_partkey IN (SELECT p_partkey FROM internal.db1.part) LIMIT 10;
+------------+
| l_shipdate |
+------------+
| 1993-02-16 |
| 1995-06-26 |
| 1995-08-19 |
| 1992-07-23 |
| 1998-05-23 |
| 1997-07-12 |
| 1994-03-06 |
| 1996-02-07 |
| 1997-06-01 |
| 1996-08-23 |
+------------+
-
這里我們通過?
catalog.database.table
?這種全限定的方式標識一張表,如:internal.db1.part
。 -
其中?
catalog
?和?database
?可以省略,缺省使用當前 SWITCH 和 USE 后切換的 Catalog 和 Database。 -
可以通過 INSERT INTO 命令,將 Hive Catalog 中的表數據,插入到 Interal Catalog 中的內部表,從而達到導入外部數據目錄數據的效果:
mysql> SWITCH internal;
Query OK, 0 rows affected (0.00 sec)mysql> USE db1;
Database changedmysql> INSERT INTO part SELECT * FROM hive.tpch100.part limit 1000;
Query OK, 1000 rows affected (0.28 sec)
{'label':'insert_212f67420c6444d5_9bfc184bf2e7edb8', 'status':'VISIBLE', 'txnId':'4'}
列類型映射?
用戶創建 Catalog 后,Doris 會自動同步數據目錄的數據庫和表,針對不同的數據目錄和數據表格式,Doris 會進行以下列映射關系。
對于當前無法映射到 Doris 列類型的外表類型,如?UNION
,?INTERVAL
?等。Doris 會將列類型映射為 UNSUPPORTED 類型。對于 UNSUPPORTED 類型的查詢,示例如下:
假設同步后的表 schema 為:
k1 INT,
k2 INT,
k3 UNSUPPORTED,
k4 INT
select * from table; // Error: Unsupported type 'UNSUPPORTED_TYPE' in 'k3
select * except(k3) from table; // Query OK.
select k1, k3 from table; // Error: Unsupported type 'UNSUPPORTED_TYPE' in 'k3
select k1, k4 from table; // Query OK.
不同的數據源的列映射規則,請參閱不同數據源的文檔。
權限管理?
使用 Doris 對 External Catalog 中庫表進行訪問時,默認情況下,依賴 Doris 自身的權限訪問管理功能。
Doris 的權限管理功能提供了對 Catalog 層級的擴展,具體可參閱?認證和鑒權?文檔。
用戶也可以通過?access_controller.class
?屬性指定自定義的鑒權類。如通過指定:
"access_controller.class" = "org.apache.doris.catalog.authorizer.ranger.hive.RangerHiveAccessControllerFactory"
則可以使用 Apache Ranger 對 Hive Catalog 進行鑒權管理。詳細信息請參閱:Hive Catalog
指定需要同步的數據庫?
通過在 Catalog 配置中設置?include_database_list
?和?exclude_database_list
?可以指定需要同步的數據庫。
include_database_list
: 支持只同步指定的多個 database,以?,
?分隔。默認同步所有 database。db 名稱是大小寫敏感的。
exclude_database_list
: 支持指定不需要同步的多個 database,以?,
?分割。默認不做任何過濾,同步所有 database。db 名稱是大小寫敏感的。