全部產品
Search
文件中心

Lindorm:訪問列存資料

更新時間:Mar 13, 2025

列存即列式儲存,是一種將資料按列進行儲存和處理的資料管理方式。Lindorm計算引擎支援將半結構化、結構化資料以列存方式進行儲存,相較於行式儲存,列式儲存的查詢回應時間更短,消耗IO更少。本文介紹如何通過計算引擎訪問Lindorm列存資料。

背景資訊

Lindorm列存是面向海量半結構化、結構化資料設計的列格式分布式儲存服務,適用於車連網、物聯網、訂單、日誌等大規模儲存情境,核心能力包括:

  • 計算分析

    Lindorm計算引擎可以訪問列存資料,完成海量資料的互動式分析和離線計算。列存提供豐富的索引能力和資料分布特徵,可以有效加速計算過程中的資料定位與排布,通過SQL即可完成海量主鍵資料的增刪改查。

  • 高吞吐

    列存引擎吞吐能力支援水平擴充,提供每分鐘TB級資料的讀寫能力。適用於車連網資料快速匯入、模型訓練資料集存取和大規模報表分析生產等高吞吐資料情境。

  • 低成本

    通過列格式高壓縮比演算法、高密度低成本介質、冷熱分離、多壓縮編碼和資料冷歸檔等技術,Lindorm列存相比自建系統儲存成本顯著降低,滿足海量資料歸檔留存等低成本儲存需求。

  • 高可用

    通過糾刪碼等技術,Lindorm列存保證了分布式資料集的高可用性,同時保證了資料訪問無單點。

  • 開源相容

    相容Iceberg開源標準介面,與Spark、Flink等多種計算引擎互聯互連,無縫對接主流資料生態。

  • 冷熱分離

    您可以根據業務需求將冷熱資料存放區在不同的介質上,減少訪問冷資料帶來的效能消耗,同時有效降低儲存成本。

前提條件

功能說明

DDL

命名空間

建立Namespace(Database)

USE lindorm_columnar;
CREATE NAMESPACE mydb;

刪除Namespace(Database)

USE lindorm_columnar;
DROP NAMESPACE mydb;

建立表

USE lindorm_columnar;
CREATE TABLE mydb.mytable (
  id INT NOT NULL,
  city STRING NOT NULL,
  name STRING,
  score INT)
PARTITIONED BY (city, bucket(128,id))
TBLPROPERTIES(
  'primary-key' = 'id,city');

以下分別對主鍵、資料分區方式進行說明。

主鍵

建立表時,可以通過設定主鍵建立主鍵表或不設定主鍵建立非主鍵表。以下將分別介紹主鍵表和非主鍵表的建立方法,以及建立時需遵循的規則。

  • 建立主建表。建立表時,設定TBLPROPERTIESprimary-key參數的值,指定表的主鍵欄位即可。主鍵表遵循以下規則:

    • 多個主鍵欄位需用英文逗號分隔。支援欄位類型:BOOLEAN、BYTE、SHORT、INT、LONG、FLOAT、DOUBLE、STRING和BINARY。

    • 列存表主鍵具備唯一性。

    • 當相同主鍵資料多次寫入,新資料將覆蓋舊資料。

    • 必須指定分區,表分區運算式欄位必須來自主鍵欄位,最後一級分區必須為bucket分區。

  • 建立非主鍵表。建立表時,不設定TBLPROPERTIES中的primary-key參數的值即可。非主鍵表無分區要求且資料無唯一性保證,允許存在重複資料。

資料分區方式

您可以在建立表時通過PARTITIONED BY([普通分區運算式],{bucket(bucketNum,bucketCol)})指定資料分區方式。

  • bucket分區運算式

    • bucketNum為分區數量,直接影響資料寫入和掃描的並發度。

      說明

      不同的bucket分區有不同的分區號(bucket_index)。bucketNum決定了一個普通分區下的bucket分區數量。

      • bucket分區號的計算方式是基於分區欄位求Hash值,然後對bucketNum取餘得出。以樣本表mydb.mytable中的資料為例,bucket_index=hash(id)%128

      • 對於每個不同的bucket_index,底層儲存將進行物理劃分。建議您在建立表前評估資料總量,併合理設定bucketNum,保證單bucket分區的資料量在50M~512M之間。

    • bucketCol為具體的bucket分區欄位。

      重要

      設定bucket分區欄位時為避免資料扭曲,需確保bucket分區欄位具有足夠的離散特徵。

    樣本

    建立表時僅指定bucket分區。

    • 樣本一:

      USE lindorm_columnar;
      CREATE TABLE mydb.mytable (
        id INT NOT NULL,
        city STRING,
        name STRING,
        score DOUBLE)
      PARTITIONED BY (bucket(1024,id))
      TBLPROPERTIES(
        'primary-key' = 'id');
    • 樣本二:

      USE lindorm_columnar;
      CREATE TABLE mydb.mytable (
        id INT NOT NULL,
        timestamp LONG NOT NULL,
        city STRING,
        name STRING,
        score DOUBLE)
      PARTITIONED BY (bucket(512,timestamp))
      TBLPROPERTIES(
        'primary-key' = 'id,timestamp');
  • 普通分區運算式

    對於普通分區運算式每個不同的值,底層儲存將進行物理劃分,保證資料掃描的裁剪能力。

    重要

    請您確保普通分區運算式的取值相對集中,常見普通分區欄位包括:日期、城市、性別等等。如果您的普通分區運算式取值過於離散,例如時間戳記,將導致列存中繼資料壓力過大。

    樣本

    建立表時同時指定普通分區和bucket分區。

    • 樣本一:

      USE lindorm_columnar;
      CREATE TABLE mydb.mytable (
        id INT NOT NULL,
        year STRING NOT NULL,
        month STRING NOT NULL,
        day STRING NOT NULL,
        city STRING,
        name STRING,
        score DOUBLE)
      PARTITIONED BY (year, month, day, bucket(1024,id))
      TBLPROPERTIES(
        'primary-key' = 'id, year, month, day');
    • 樣本二:

      USE lindorm_columnar;
      CREATE TABLE mydb.mytable (
        id INT NOT NULL,
        date STRING NOT NULL,
        city STRING NOT NULL,
        name STRING,
        score DOUBLE)
      PARTITIONED BY (date, city, bucket(1024,id))
      TBLPROPERTIES(
        'primary-key' = 'id,date,city');

查看當前Namespace下的表

USE lindorm_columnar;
USE mydb;
SHOW TABLES;

查看已存在的表

您可以執行以下SQL語句查看錶結構。

USE lindorm_columnar;
SHOW CREATE TABLE mydb.mytable;
DESC mydb.mytable;

刪除指定表

USE lindorm_columnar;
-- 刪除表保留資料檔案
DROP TABLE mydb.mytable;
-- 刪除表刪除資料檔案
DROP TABLE mydb.mytable PURGE;

清空表中資料

USE lindorm_columnar;
TRUNCATE TABLE mydb.mytable;

分區

刪除分區

您可以通過DELETE FROM文法指定WHERE條件匹配分區來刪除分區,樣本如下。

USE lindorm_columnar;
DELETE FROM mydb.mytable WHERE city = 'beijing';

DML

在表中插入資料

  • 樣本一:

    USE lindorm_columnar;
    INSERT INTO mydb.mytable VALUES (0, 'beijing', 'zhang3', 99);
  • 樣本二:

    USE lindorm_columnar;
    INSERT INTO mydb.mytable SELECT id, city, name, score FROM another_table;

查詢表中的資料

  • 樣本一:

    USE lindorm_columnar;
    SELECT * from mydb.mytable where id=0;
  • 樣本二:

    USE lindorm_columnar;
    SELECT count(1), sum(score) from mydb.mytable where city = 'beijing';

分區整理

在列存分區寫入資料,經過一段時間後,您可以執行rewrite_data_filesrewrite_manifest命令,整理分區資料,可以將零散的小檔案合并為大檔案,減少資料或中繼資料冗餘,提升資料查詢效能。詳細說明,請參見rewrite_data_files文法rewrite_manifest文法

說明

執行rewrite_data_filesrewrite_manifest命令時,會佔用資料庫資源,建議在業務低峰期執行。

  • 樣本一:

    USE lindorm_columnar;
    CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable');
  • 樣本二:

    USE lindorm_columnar;
    CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable', where => 'city=\"beijing\"');
  • 樣本三:

    USE lindorm_columnar;
    CALL lindorm_columnar.system.rewrite_manifest('mydb.mytable');

冷熱介質

在資料管理時,為最佳化成本與效能,通常會選擇將高頻訪問的資料存放區在高效能介質上,而對於長時間未訪問的歷史資料,則希望將其遷移到低成本的儲存介質中。Lindorm列存支援三級冷熱分層解決方案(從熱到冷分別為L1、L2和L3),可以根據業務需求靈活制定列存資料的冷熱轉換策略。通過資料湖服務自動完成資料在冷熱介質之間的自動轉儲,協助您有效管理儲存成本而不犧牲關鍵業務的響應速度。

重要

Lindorm列存資料自動冷熱轉換功能,需聯絡Lindorm支援人員(DingTalk號:s0s3eg3)開通。

參數配置

您可以通過在建立列存表時定義CHS(Cold or Hot Storage)屬性,以列存表的時間分區為粒度,定義資料冷熱轉儲。配置CHS的參數說明如下:

參數

說明

CHS

配置該參數即表示開啟冷熱分離,可以配置為:

  • 一個長整數(單位為秒)。

    • 如果分區資料時間距離目前時間小於等於該閾值,則存入L1層。

    • 如果分區資料時間距離目前時間大於該閾值,自動轉儲到L2層。

    說明

    如:'CHS'='259200',表示冷熱分離成兩層。

    • 分區資料時間距離目前時間小於等於259200秒時,資料存入L1層。

    • 分區資料時間距離目前時間大於259200秒時,資料自動轉儲到L2層。

  • 兩個長整數(單位為秒)。用逗號分隔,形如num0, num1,要求num0<num1

    • 如果分區資料時間距離目前時間小於等於第一個閾值,則存入L1層。

    • 如果分區資料時間距離目前時間大於第一閾值,且小於等於第二閾值,則自動轉儲到L2層。

    • 如果分區資料時間距離目前時間大於第二閾值,則自動轉儲到L3層。

    說明

    如:'CHS'='259200, 864000',表示冷熱分離成三層。

    • 分區資料時間距離目前時間小於等於259200秒時,資料存入L1層。

    • 分區資料時間距離目前時間大於259200秒且小於等於864000秒時,資料自動轉儲到L2層。

    • 分區資料時間距離目前時間大於864000秒後,資料自動轉儲到L3層。

CHS_L1

配置L1層選用的儲存介質,參數格式為:'CHS_L1'='storagetype=目標儲存類型'

說明

如果在建立表時沒有配置CHS_L1指定儲存介質,則預設使用容量型雲端儲存。

如果您是雲端儲存使用者,目標儲存類型可選值如下:

  • CAPACITY_CLOUD_STORAGE:容量型雲端儲存(預設值)。

  • STANDARD_CLOUD_STORAGE:標準型雲端儲存。

  • PERFORMANCE_CLOUD_STORAGE:效能型雲端儲存。

  • CLOUD_ARCHIVE_STORAGE:歸檔型儲存。

    說明

    歸檔型儲存類型目前在內測中,如需使用請聯絡Lindorm支援人員(DingTalk號:s0s3eg3)開通。

如果您是本地碟使用者,目標儲存類型可選值如下:

  • CAPACITY_CLOUD_STORAGE:容量型雲端儲存(預設值)。

  • LOCAL_SSD_STORAGE:本地SSD儲存。

  • LOCAL_HDD_STORAGE:巨量資料型。

  • LOCAL_EBS_STORAGE:本地ESSD雲端硬碟。

CHS_L2

配置L2層選用的儲存介質,參數格式與可選值同CHS_L1。

說明

CHS_L2參數必須配置。

CHS_L3

配置L3層選用的儲存介質,參數格式與可選值同CHS_L1。

說明

如果您的CHS參數為兩個長整數時,CHS_L3參數必須配置。

CHS_EXP

配置分區資料時間的提取方法,您需要將其定義為形如:toSec(${column0},${pattern0},${column1},${pattern1},....${columnN},${patternN})

其中:

  • columnN:表示時間的枚舉分區欄位,支援的資料類型為:INTEGER、LONG、STRING和DATE。

  • patternN:對應時間分區欄位的格式,可選值如下:

    • yyyy:表示年。

    • MM:表示月。

    • dd:表示日。

    • HH:表示小時。

    • mm:表示分鐘。

  • toSec系統函數能夠計算出對應時間分區範圍的最大資料時間。樣本如下:

    • 如果時間分區的3個欄位為year/month/day,對於year=2023, month=10,day=2這個分區,toSec(year,yyyy)返回資料時間為2023-12-31 23:59:59,toSec(year, yyyy, month, MM)返回資料時間為2023-10-31 23:59:59,toSec(year, yyyy, month,MM,day,'dd')返回資料時間為2023-10-02 23:59:59

    • 如果時間分區欄位為date,對於date=2023-10-02這個分區,toSec(date, yyyy-MM-dd)返回資料時間為2023-10-02 23:59:59

Lindorm計算引擎會基於CHS_EXP擷取時間分區的最巨量資料時間,結合CHS中定義的時間閾值範圍,將分區資料轉儲到相應的分層介質。

樣本

  • 樣本一:

    建立表table0,按年,月,日三個欄位分區,欄位名稱為year,month,day。定義冷熱分層策略為:1個月(2592000秒)以前的資料自動轉儲到容量型雲端儲存。建表語句如下:

    CREATE TABLE table0 (col0 INT,year STRING,month STRING,day STRING)
    PARTITIONED BY  (year,month)
    TBLPROPERTIES 
    'CHS'='2592000',
    'CHS_L2'='storagetype=CAPACITY_CLOUD_STORAGE',
    'CHS_EXP'='toSec(year,yyyy,month,MM,day,dd)'
    );
  • 樣本二:

    修改table0冷熱分層策略為:1個月(2592000秒)以前的資料自動轉儲到容量型雲端儲存,超過3個月(5184000秒)後自動轉儲到歸檔型儲存,其他規則不變。更新表語句如下:

    ALTER TABLE table0
    SET TBLPROPERTIES (
    'CHS'='2592000,5184000',
    'CHS_L2'='storagetype=CAPACITY_CLOUD_STORAGE',
    'CHS_L3'='storagetype=CLOUD_ARCHIVE_STORAGE',
    'CHS_EXP'='toSec(year,yyyy,month,MM,day,dd)'
    );
  • 樣本三:

    建立table1,按天分區,欄位名為dt,形如:2020/12/1。定義冷熱分層策略為:1個月(2592000秒)以前的資料自動轉儲到容量型雲端儲存,超過3個月(5184000秒)後自動轉儲到歸檔型儲存。建表語句如下:

    CREATE TABLE table1 (col0 INT,dt STRING)
    PARTITIONED BY  (dt)
    TBLPROPERTIES (
    'CHS'='2592000,5184000',
    'CHS_L2'='storagetype=CAPACITY_CLOUD_STORAGE',
    'CHS_L3'='storagetype=CLOUD_ARCHIVE_STORAGE',
    'CHS_EXP'='toSec(dt,yyyy/MM/dd)'
    );
注意事項
  • 在建立表時,您可以指定CHS參數。如果後續需要更改冷熱分層策略,可以通過執行ALTER TABLE ...SET TBLPROPERTIES...語句來調整配置。

  • 錯誤的CHS配置不會影響表建立與更新,但會導致無法自動觸發冷熱介質轉換功能。

  • 資料的冷熱轉儲過程是通過非同步方式觸發的。在整個轉儲過程中及完成後,資料訪問均不受影響,但基於不同儲存介質,訪問效能可能會有所變化。

  • 僅支援基於列存表的時間分區來實現資料冷熱分層策略,暫不支援其他方式。

最佳實務

您可以通過以下方案,加速資料查詢或計算。

主鍵資料查詢

如果表中儲存了海量資料集,查詢時可以指定通過主鍵過濾條件,實現加速效果。查詢時,主鍵的資料範圍設定得越小,加速效果越好。

假設表結構如下:

USE lindorm_columnar;
CREATE TABLE orders (
o_orderkey       INT NOT NULL,
o_custkey        INT,
o_orderstatus    STRING,
o_totalprice     DOUBLE,
o_orderdate      STRING,
o_orderpriority  STRING,
o_clerk          STRING,
o_shippriority   INT,
o_comment        STRING)
PARTITIONED BY (bucket(1024,o_orderkey))
TBLPROPERTIES(
'primary-key' = 'o_orderkey');           
  • 樣本一:

    USE lindorm_columnar;
    SELECT * FROM orders WHERE o_orderkey=18394;
  • 樣本二:

    USE lindorm_columnar;
    SELECT count(*) FROM orders WHERE o_orderkey>100000 AND o_orderkey<200000;
  • 樣本三:

    USE lindorm_columnar;
    SELECT count(*) FROM orders WHERE o_orderkey>100000;

添加分區過濾

Lindorm列存引擎中不同分區之間彼此物理隔離,因此,通過添加分區過濾條件,可以加速資料查詢。

假設表結構如下:

USE lindorm_columnar;
CREATE TABLE orders (
o_orderkey       INT NOT NULL,
o_custkey        INT,
o_orderstatus    STRING,
o_totalprice     DOUBLE,
o_orderdate      STRING NOT NULL,
o_orderpriority  STRING,
o_clerk          STRING,
o_shippriority   INT,
o_comment        STRING)
PARTITIONED BY (o_orderdate, bucket(1024,o_orderkey))
TBLPROPERTIES(
'primary-key' = 'o_orderdate,o_orderkey');
  • 樣本一:

    USE lindorm_columnar;
    SELECT o_orderdate, count(*) FROM orders WHERE o_orderdate='2022-01-01' GROUP BY o_orderdate;
  • 樣本二:

    USE lindorm_columnar;
    SELECT o_orderdate, count(*) FROM orders WHERE o_orderdate>='2022-01-01' AND o_orderdate<='2022-01-07' GROUP BY o_orderdate;

查詢加速

對指定表或者表中的指定分區進行資料整理(Rewrite),可以增強資料的有序性或緊湊性,從而提升資料掃描效能。

假設表結構如下:

CREATE TABLE mydb.mytable (
  id INT NOT NULL, 
  city STRING NOT NULL, 
  name STRING, 
  score INT)
partitioned by (city, bucket(4, id))
tblproperties('primary-key' = 'id,city');
  • 樣本一:對mydb.mytable全表進行資料整理。

    CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable');
  • 樣本二:對指定分區進行資料整理。

    CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable', where => 'city=\"beijing\"');

完成資料整理後,如果想要進一步提升後續查詢的效率,可以執行以下語句設定表的相關參數來加速後續查詢:

ALTER TABLE mydb.mytable SET TBLPROPERTIES ('read.scan-major-rewritten-files-only' = true);

參數說明

read.scan-major-rewritten-files-only:指定資料查詢範圍。資料類型為BOOLEAN。取值如下:

  • true:只查詢已完成資料整理的資料,忽略增量寫入且未完成資料整理的資料。

  • false:預設值。查詢所有資料。

非主鍵條件查詢

針對分區整理過程,列存表預設按主鍵排序,可以在建表後按需配置排序鍵,從而加速非主鍵條件查詢。

重要

自訂排序鍵加速查詢效果需要在配置排序鍵後進行分區整理,且只掃描已進行分區整理的資料,不再掃描增量資料。

假設表結構如下:

USE lindorm_columnar;
CREATE TABLE orders (
o_orderkey       INT NOT NULL,
o_custkey        INT,
o_orderstatus    STRING,
o_totalprice     DOUBLE ,
o_orderdate      STRING ,
o_orderpriority  STRING,
o_clerk          STRING,
o_shippriority   INT,
o_comment        STRING)
PARTITIONED BY (bucket(1024,o_orderkey))
TBLPROPERTIES(
'primary-key' = 'o_orderkey',
'read.scan-major-rewritten-files-only' = 'true');

執行以下語句配置排序鍵:

ALTER TABLE orders WRITE ORDERED BY o_shippriority,o_totalprice;

執行以下語句整理分區:

CALL lindorm_columnar.system.rewrite_data_files(table => 'orders');

您可以使用以下SQL語句查詢已完成分區整理的表中的資料。

  • 樣本一:

    USE lindorm_columnar;
    SELECT count(*) FROM orders WHERE o_shippriority=0;
  • 樣本二:

    USE lindorm_columnar;
    SELECT count(*) FROM orders WHERE o_shippriority=0 AND o_totalprice>999.9;