查询性能提升 10 倍、存储空间节省 65%,Apache Doris 半结构化数据分析方案及典型场景

Doris 2.0 导入性能提升2-8倍的优化手段 阅读详情

随着业务的蓬勃发展,各企业对数据处理的灵活性和可扩展性提出了更高的要求。在此背景下,JSON、XML 等半结构化数据凭借其较强的灵活性在众多企业得到广泛应用。然而,传统关系型数据库结构严格,难以应对半结构化数据的复杂性及多样性。为有效存储及分析这些数据,Apache Doris 针对不同应用场景提供了 Array、Map、Struct、JSON、VARIANT半结构化数据存储分析解决方案。

本文我们将聚焦企业最普遍使用的 JSON 数据,分别介绍业界传统方案以及 Apache Doris 半结构化数据存储分析的三种方案,并通过图表直观展示这些方案的优势与不足。同时,结合具体应用场景,分享不同需求场景下的使用方式,帮助用户快速选择最合适的 JSON 数据存储及分析方案。

半结构化数据特点及挑战

业界通常将数据分为结构化数据、非结构化数据、半结构化数据这三大类型:

  • 结构化数据:关系型数据库是一种典型的结构化数据存储方式,其核心特点是结构严格且固定。例如,一个包含五列数据的表,其数据类型可能是字符串(string)、整数(int)或日期(date)等。字段名和类型均是预先设定、不可轻易改变,具备读写性能出色的优势。
  • 非结构化数据:非结构化数据指没有固定结构的数据,例如文本、音频和视频等,这类数据缺乏明显的结构特征。例如,进行文本检索时,需要查找特定的关键字或短语。(Apache Doris 从 2.0 版本开始,提供了倒排索引等功能,可以实现对非结构化文本数据的高效检索,包括关键词检索、短语检索等。)
  • 半结构化数据: 半结构化数据虽然拥有一定的结构,但不严格固定,具有很强的灵活性。比较典型的是 JSON 格式,可以便捷地增加新字段或删除不需要的字段,以适应数据交互和存储的需求。

Github 用户操作记录日志 GH Archive 是典型的半结构化 JSON 数据,通过下方示例 CreateEvent 和 PushEvent ,展示真实的数据。

  • CreateEvent

    {
      "id": "37066529202",
      "type": "CreateEvent",
      "actor": {
        "id": 151583193,
        "login": "BlankTMing",
        "display_login": "BlankTMing",
        "gravatar_id": "",
        "url": "https://api.github.com/users/BlankTMing",
        "avatar_url": "https://avatars.githubusercontent.com/u/151583193?"
      },
      "repo": {
        "id": 780596894,
        "name": "BlankTMing/ManifestAutoUpdate-",
        "url": "https://api.github.com/repos/BlankTMing/ManifestAutoUpdate-"
      },
      "payload": {
        "ref": "2715611_469785097560218038",
        "ref_type": "tag",
        "master_branch": "main",
        "description": null,
        "pusher_type": "user"
      },
      "public": true,
      "created_at": "2024-04-01T23:00:00Z"
    }
    
  • PushEvent

    {
      "id": "37066529220",
      "type": "PushEvent",
      "actor": {
        "id": 73488070,
        "login": "hafsa1319",
        "display_login": "hafsa1319",
        "gravatar_id": "",
        "url": "https://api.github.com/users/hafsa1319",
        "avatar_url": "https://avatars.githubusercontent.com/u/73488070?"
      },
      "repo": {
        "id": 746560097,
        "name": "hafsa1319/akademi_report",
        "url": "https://api.github.com/repos/hafsa1319/akademi_report"
      },
      "payload": {
        "repository_id": 746560097,
        "push_id": 17799451996,
        "size": 1,
        "distinct_size": 1,
        "ref": "refs/heads/main",
        "head": "fc7a15d71539a3588f43e41f9034bfb4b4464358",
        "before": "e29be382e67485ff5a8a88264f9b3272b2366c3a",
        "commits": [
          {
            "sha": "fc7a15d71539a3588f43e41f9034bfb4b4464358",
            "author": {
              "email": "73488070+hafsa1319@users.noreply.github.com",
              "name": "hafsa1319"
            },
            "message": "Add or update home/hafsa-report/htdocs/report.hafsa.de/akademi/csv/telcHS2402.csv",
            "distinct": true,
            "url": "https://api.github.com/repos/hafsa1319/akademi_report/commits/fc7a15d71539a3588f43e41f9034bfb4b4464358"
          }
        ]
      },
      "public": true,
      "created_at": "2024-04-01T23:00:00Z"
    }
    

参考 Wikipedia 上的定义,结合实际业务落地的经验,半结构化数据具有以下特点:

semi-structured-definition.png

  • 不严格遵循结构化表模型:半结构化数据不严格遵循关系数据库中的表格结构,通常包含标签(tags)或其他形式的标记,以表明其语义或字段名。以上方 GH Archive 示例,“id”, “type”, “payload” 是标签或者字段名。

  • 自描述结构但不固定: 半结构化数据具有一定自描述性,一般通过键值对(Key-Value Pairs)描述内部结构。这种结构并不固定,可能包含不同数量的字段或类型。以上方 Github Event 示例,PushEvent 的 payload 字段就比 CreateEvent 多了ref head commits 等字段。

  • 通常有嵌套结构: 嵌套结构的复杂性较高,表现为一个结构体内部嵌套另一个结构体,甚至结构体或数组中再嵌套其他结构体或数组,形成多层次、复杂的数据结构。以上方 GH Archive 示例,CreateEvent 中 actor repo payload 有简单的嵌套子字段,而 PushEvent 的 payload 中 commits 字段则出现了数组嵌套结构体、结构体再嵌套结构体的复杂结构。

上述特点为半结构化数据的存储和分析带来很大的挑战,也是业界数据库要解决的主要问题:

  • 如何支持灵活的 Schema:半结构化数据具备较高的灵活性,字段随着业务发展而增加/减少,类型也可能变化,数据中的嵌套结构也让字段变的更加复杂,因此要求数据库能够支持灵活的 Schema。

  • 如何高效存储:半结构化数据中包含大量重复的自描述内容,比如大量重复的字段名,通常是由机器产生。如果按原始数据存储,数据冗余存储带来的资源浪费非常高,因此要求数据库能够高效存储。

  • 如何极速分析:半结构化数据通常为文本形式,直接对文本解析和分析虽然可行但性能较差。特别是在分组、聚合、过滤等操作时,要从大量的字段中分析其中的几个字段,将带来很多不必要的 IO 和解析开销。

接下来,我们就以 JSON 数据为例,了解业界为应对这些挑战的常见解决方案。

传统解决方案

01 通过 ETL 转为结构化数据

方案一是在 ETL 过程将半结构化数据转化为结构化数据,主要借助 ETL 工具 / 数据库导入过程中实现。比如在 Doris 中,可以借助导入的 JSON 字段映射功能,将数据映射到预设的表结构中。

该方案的优势是:转化为结构化形式后,可充分利用结构化数据处理的优势,提供较高的存储压缩率和出色的分析性能。

该方案的问题是:当上游数据源字段发生变化(如增加或删除字段)时,下游表结构也进行相应修改。如不修改表结构,新增的数据将无法完整写入。而修改过程非常繁琐,通常需要多个团队协作与配合,处理起来并不高效,且这种方式也丧失了半结构化数据的灵活性。

02 String 存储和 JSON 函数分析

方案二是将 JSON 数据转存到 String 字段中,String 支持存储任意文本数据,可解决 Schema 灵活性差的问题。当需要对这些 JSON 数据查询分析时,可使用专门的 JSON 函数提取所需字段,如可通过json_extract、json_extract_int、json_extract_double等函数解析并提取特定字段值。

该方案的问题是:每次查询都需要使用 JSON 函数解析和遍历整行 JSON 文本,效率低、分析性能差。此外,由于 JSON 文本以行为单位进行存储,其压缩效率不如列式存储高。

03 Elasticsearch Dynamic Mapping

方案三为 Elasticsearch 的 Dynamic Mapping ,该方案可自动识别新增 JSON 数据的字段名和类型,并将字段动态添加到 Elasticsearch Index Mapping (类似 Table Schema) 中。

该方案的问题是:

  • 字段类型一旦确定不可更改,若字段首次被写入为整型(int),后续则必须保持为整型;如果尝试写入非整型数据(如浮点型 float 或者字符串类型 string),Elasticsearch 将拒绝写入并可能丢弃这条数据,限制了数据类型随业务发展而演变的灵活性。

  • 当写入数据包含大量字段时,Elasticsearch Mapping 会迅速膨胀,这是因为 Elasticsearch 会将每个字段展开,字段多的时候(比如超过 500)元数据压力增大,严重影响查询,而且 Mapping 只增不减,即便删除字段多的行也不能减少元数据。

基于 Apache Doris 的半结构化数据存储及分析方案

针对传统方案存在的问题,Apache Doris 结合不同场景下对半结构化数据存储和分析的需求,提供了三种解决方案,用户可以根据实际场景灵活选择。

01 Array Map Struct

Array、 Map 、Struct 数据类型支持嵌套的固定 Schema,常用于用户行为和画像分析、查询数据湖中 Parquet ORC 等格式数据的场景。

Array Map Struct 可以存储复杂结构数据,Array 存储相同类型的数组,Map 存储键值对(Key-Value ),Struct 存储 n 元组,它们之间可以相互嵌套。

  • 优势:采用列式存储,可实现较高的压缩率,节省大量存储空间;因嵌套结构的字段和类型是预先定义且相对固定的,在写入和查询时不再需要动态推断数据的 Schema,执行效率较高。
  • 不足:虽可以预先定义出复杂的嵌套结构,但是一旦定义后结构不能随着数据变化自适应。

02 JSON

JSON 数据类型支持**嵌套的不固定 Schema,**常用于点查和部分分析场景。

JSON 数据类型是二进制存储类型,具备 JSON String 的灵活性,任意合法的 JSON 数据均可进行存储,分析时通过 JSON 函数来提取对应字段。

  • 优势:点查性能好,JSON 采用行存形式进存储,且 JSON 在写入过程中已完成 JSON 的解析,可从二进制中直接读取数据,查询效率至少比 JSON String 快 2 倍。
  • 不足:JSON 存储压缩率低于列存,存储成本也相对较高。同时,因在查询时需要先读取整行 JSON 二进制数据、再读取需要分析的字段,读取效率不如行存高效。

03 VARIANT

VARIANT 数据类型支持嵌套的不固定 Schema,常用于 Log、 Trace、 IoT 等分析场景,业界类似的解决方案还有前文所述的 Elasticsearch Dynamic Mapping。

VARIANT 数据类型可以存储任何合法的 JSON,可自动从 JSON 中抽取字段并推断其类型,并将这些字段存储为 VARIANT 列的子列。这种列式存储方式使得 VARIANT 具备很好的分析性能,当进行聚合/过滤/排序等查询时,只需要读取 Variant 子列数据即可,不会产生额外的数据解析开销,查询性能可获得数量级的提升。

相比于 Elasticsearch Dynamic Mapping ,Doris VARIANT 的优势在于:

  • 允许写入不同字段类型,数据文件内部使用最小公共类型存储,数据文件之间采用不同类型存储,互不影响。查询时,可以使用最小公共类型或者用户指定的类型查询。
  • 可以将出现频次较低的字段合并为二进制 JSON 存储,以此避免字段过多引发子列和文件膨胀的问题,可以兼顾性能和数据结构的灵活性。

在基于 ClickBench 的测试数据集上,VARIANT 有很好的性能表现。

VARIANT.png

  • 在存储方面,其性能与 ETL 转结构化方案相当,均有较低的存储占用;相较于 JSON String,存储资源节省达65%。
  • 在查询方面,其性能与 ETL 转结构化方案相当,冷热查询性能差异在 10% 以内;相较于 JSON String 来说,冷查询有 10 倍以上提升、热查询有 8.4 倍的提升,在用户实际的应用场景中,也验证了相似的结果。

方案对比

为直观比较各方案,我们通过图表来展示 ETL 转结构化、JSON String/Binary、Elasticsearch Dynamic Mapping 、Array Map Struct、JSON、VARIANT 等方案的特点,从 Schema 的灵活性、存储效率和分析性能等维度评估各方案的优势和局限性。 (横坐标轴为 Schema 灵活性、纵坐标轴为存储效率 & 分析性能)

方案对比.jpeg

由上图可得出结论:

  • ETL 转结构化方案的的分析性能表现最佳,但 Schema 灵活性最差。

  • JSON String / Binary 的 Schema 灵活性最佳,但是其分析性能均比较低。

  • Doris VARIANT 和 Dynamic Mapping 在灵活性和性能方面表现均比较好,但整体而言 Doris VARIANT 更优,不仅是存储和分析性能强于 Dynamic Mapping,还体现在 VARIANT 能够很好解决字段类型固定和字段个数膨胀的痛点问题。

典型应用场景

接下来,我们将从用户常见的典型应用场景入手,介绍在不同场景中应选择哪种解决方案,以获得最佳的使用体验和性能表现。

01 用户画像与行为分析场景

在用户画像与行为场景中,有时会遇到包含多个值的复杂标签,比如 “喜欢的颜色”,可将颜色编号成整数,然后用 ARRAY<INT> 存储该标签。

CREATE TABLE `customer_profile` (
  `rid` bigint NOT NULL,
  `pid` bigint NOT NULL,
  `last_update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `tag_cdp_1` int NULL,
  `tag_cdp_2` varchar,
  `tag_cdp_3` varchar,
  `tag_cdp_4` int NULL,
  `tag_cdp_5` varchar,
  `tag_1` text NULL,
  `tag_2` array<int> NULL,
  `tag_3` int NULL,
  `tag_4` text NULL,
  `tag_5` array<int> NULL,
  `tag_6` int NULL,
  `tag_7` array<int> NULL
) ENGINE=OLAP
UNIQUE KEY(`rid`, `pid`)
DISTRIBUTED BY HASH(`rid`, `pid`) BUCKETS 30

查询时可以筛选多值标签是否包含某些值,比如使用 array_overlap 函数检查 tag_5 里面是否有 3, 6 或者 8。

SELECT * FROM customer_profile
WHERE pid = 1001
  AND array_overlap(tag_5, [3, 6, 8])

02 数据湖查询加速场景

在数据湖查询加速场景中,在对接 Hive、Iceberg、Hudi 等外部数据源时,经常出现 ARRAY MAP STRUCT 等复杂嵌套数据类型,我们可以将这些数据类型直接映射到 Doris 内置的 ARRAY MAP STRUCT 类型。

如下示例,在 Doris 中创建 Hive CATALOG 并切换,可以快速读取 Hive 中的表。还可通过 DESC 查看表 st 结构中所包含的复杂嵌套类型,包括 ARRAY<FLOAT> 类型 的 usage 字段、MAP<STRING, FLOAT> 类型的 signal 字段、MAP 嵌套 ARRAY 的 ext 扩展字段。

CREATE CATALOG hive PROPERTIES (
    'type'='hms',
    'hive.metastore.uris' = 'thrift://172.0.0.1:9083',
    'hadoop.username' = 'hive'
);

SWITCH hive;

DESC st;
+--------+---------------------------+------+-------+---------+-------+
| Field  | Type                      | Null | Key   | Default | Extra |
+--------+---------------------------+------+-------+---------+-------+
| id     | VARCHAR(255)              | Yes  | true  | NULL    |       |
| status | TINYINT                   | Yes  | false | NULL    |       |
| start  | DATETIME                  | Yes  | false | NULL    |       |
| end    | DATETIME                  | Yes  | false | NULL    |       |
| usage  | ARRAY<FLOAT>              | Yes  | false | NULL    |       |
| signal | MAP<STRING, FLOAT>        | Yes  | false | NULL    |       |
| ext    | MAP<STRING, ARRAY<INT>>   | Yes  | false | NULL    |       |
+--------+---------------------------+------+------+---------+-------+

下面的查询首先筛选出 2013-11-04 的数据,然后从ext这个 MAP 字段中,筛选出 Key 为'tags' 的 ARRAY 中包含55的记录,最后按status字段进行分组,使用array_avg函数计算usage这个 ARRAY 类型字段的平均值。

SELECT status, avg(array_avg(usage)) as avg_usage FROM st
WHERE array_contains(ext['tags'], 55)
  AND start >= '2013-11-04 00:00:00'
  AND   end <= '2013-11-04 23:59:59'
GROUP BY status;

03 Log 场景

在日志存储和分析的场景中,日志数据通常包含一些静态字段(时间戳、机器名称、文件路径)、日志文本消息以及扩展字段。扩展字段用于存储不固定的信息或属性,例如某个日志中可能包含一个名为ext的扩展字段,用于记录与日志相关的特定信息或数据。如下所示:

{
    "time": 2024-04-09 16:06:03.684886
    "source": "fluentd_tcp"
    "host": "host1"
    "status": "info"
    "filepath": "path1"
    "container_id": "xxx"
    "container_name": "xxx"
    "message": "....."
    "ext": {
        "nameSpace": "kube-public",
        "level": "info",
        "service": "console-media",
        "category": "debug",
        "tag": "[]",
        "serviceID": "console-media-6b57fc7758-nplck",
        "date_ns": 886517,
        "index": "default",
        "cluster": "UcloudKubernetes"
    }
}

包含扩展字段的日志数据结构使得数据扩展更加便捷、灵活和多样化,但也对数据的存储和分析技术提出了更高的要求。而使用 VARIANT 可以很好的解决这一问题。

在建表时,如果扩展字段ext使用 VARIANT 类型,可使数据灵活写入。

CREATE TABLE log (
    `time` datetime(6) NULL,
    `source` text NULL,
    `host` text NULL,
    `status` text NULL,
    `filepath` text NULL,
    `container_id` text NULL,
    `container_name` text NULL,
    `message` text NULL,
    `ext` variant NULL,
    INDEX idx1 (`message`) USING INVERTED PROPERTIES("parser" = "chinese")
)

在查询时,可以使用特定的语法访问 VARIANT 的子列。如下所示的查询中,主要按照时间和服务名称来统计错误数量。

  • 首先,在WHERE条件中将时间戳转换为小时单位,并提取出EXT字段中的service字段值。

  • 接着,计算满足条件的记录数量(count)并进行聚合。如需提取namespace字段时(variant类型的子字段),无需读取整个 VARIANT 字段的内容,而只需访问 VARIANT 扩展的特定子列即可,这种数据访问方式使得查询性能更高。

  • 最后,按照小时和服务名称对结果进行分组,并按时间进行排序,就可以得到一个错误趋势图。该趋势图可帮助用户直观地了解系统在不同时间段内的错误发生情况,为故障排查和性能优化提供有力支持。

SELECT
hour_floor(`time`) as hour,
cast (ext['service'] as text) as service,
count() as cnt
FROM log WHERE time >= t1 AND time < t2
AND (`status` = "error") AND (`source` = "abc")
AND ext['nameSpace'] = "bcd"
GROUP BY hour, service
ORDER BY hour LIMIT 100;

在日志场景使用 VARIANT 的优势在于:

  • 允许字段类型变化,不会因为数据变化而出现写入异常。

  • 可自动处理扩展字段增减,过期删除的数据字段不会残留。

  • 相比 String 或 JSON ,其压缩率更高、分析性能也更强。

04 Trace 场景

Trace 场景通常应用于可观测领域,特别是在容器化微服务环境中。在这种环境下,服务之间的调用可能会产生大量的跟踪数据。例如,一个请求可能经过多个服务,每个服务都会生成一条 Trace 数据,这些 Trace 数据对于问题诊断和性能分析至关重要。

Trace 通常包含attrs属性字段,这些字段均是可扩展的。由于不同的模块和服务输出的格式可能有所不同,因此无法要求其具备固定的 Schema。在其他数据库中,通常会使用 Map 来存储 attrs字段,Map 的 Key 的个数是可以扩展的,但在查询某个 Key 对应的 Value 时,需要遍历所有 Key Value 对,性能较低,而这个操作在 Trace 场景中比较常见。

{
    "time: "2024-04-09 16:13:51.381141",
    "message": "...",
    "__namespace": "tracing",
    "source": "opentelemetry",
    "service": "iov-fleet-mqtt",
    "operation": "fleet/ListFleets",
    "status: "ok",
    "parent_id": "0",
    "resource": "fleet/ListFleets",
    "span_id": "xxxx",
    "trace_id": "xxxx",
    "duration": 3810,
    "start": 1712650431181241,
    "attrs": {
        "rpc_system": "grpc",
        "rpc_method": "ListFleets",
        "service_sub": "iov-fleet-mqtt",
        "k8s_cluster": "sh-test-uk8s",
        "date_ns": 141210,
        "rpc_service": "fleet.FleetService",
        "service_name": "iov-fleet-mqtt",
        "rpc_grpc_status_code": 0
    }
}

为了更好的满足这种需求,可以使用 Doris 的 VARIANT 列类型来存储 attrs 字段。当进行查询分析时,与 Log 场景类似,可以根据特定条件高效地筛选和提取这些属性字段,避免遍历整个 Map 的性能开销。

CREATE TABLE trace (
    `time` datetime(6) NULL,
    `message` text NULL,
    `source` text NULL,
    `service` text NULL,
    `endpoint` text NULL,
    `operation` text NULL,
    `status` text NULL,
    `parent_id` text NULL,
    `resource` text NULL,
    `span_id` text NULL,
    `trace_id` text NULL,
    `duration` bigint(20) NULL,
    `start` bigint(20) NULL,
    `attrs` variant NULL
)

例如,如果查询中涉及到'e``rror``_``stack``'`` ``IS NOT NULL的条件,使用 VARIANT 列的查询效率比较高,原因是无需读取整个attribute的 JSON 结构,只需读取与errorStack相关的部分。此外,通过利用索引(如 ZoneMap 索引或倒排索引),可以进一步加速此类查询。

SELECT
`time`, `message`, `source`, `service`, `endpoint`, `operation`, `status`, `parent_id`, `resource`, `span_id`, `trace_id`, `duration`, `start`, cast(`attrs` as text) as `attrs`
FROM trace
WHERE time >= t1 AND time < t2
AND `service` = "pms-java-gate"
AND attrs['error_stack'] IS NOT NULL
ORDER BY `time` DESC LIMIT 50

在 Trace 场景下,VARIANT 有下面一些优势:

  • 按 Trace 扩展字段中的某一个进行筛选,效率比 JSON 和 MAP 更高。
  • 相比 JSON 或 MAP,其存储压缩率更高。
  • Trace 扩展字段可以随意增减。

05 IoT 车联网

IoT 车联网场景中,有许多设备或车辆具备标签字段(如 tags),这些字段可能包含数值和数组。

{
    "date": 20240114,
    "plate_name": "xxx",
    "base_dir": "xxx",
    "pack_dir": "xxx",
    "naive_gt_dir": "xxx",
    "gt_dir": "xxx",
    "sync_dir": "xxx",
    "sync_index": [1755],
    "lidar_dir": "xxx",
    "calib_dir": "xxx",
    "weather": NULL,
    "scene": NULL,
    "tags": {
        "a": 2,
        "b": [0,1,0,0,1],
        "c": [0,0,0,0,0],
        "d": 0
    }
}

建表时,tags 字段使用 VARIANT 类型。

CREATE TABLE cars (
    `time` datetime(6),
    `name` TEXT,
    `base_dir` TEXT,
    `pack_dir` TEXT,
    `naive_gt_dir` TEXT,
    `gt_dir` TEXT,
    `sync_dir` TEXT,
    `lidar_dir` TEXT,
    `calib_dir` TEXT,
    `weather` TEXT,
    `scene` TEXT,
    `tags` VARIANT
)

查询时,对于 tags 里面的数值字段 a 可以用普通的比较条件,对于 tags 中的数组字段 b,可以使用 array_contains 来检查是否包含特定值。

SELECT * 
FROM cars
WHERE 
time >= t1 AND time < t2
AND tags['a'] > 10
AND array_contains(tags['b'], 1)
ORDER BY time DESC LIMIT 100

在 IoT 和车联网场景下,VARIANT 的优势主要包含以下几点:

  • 相对于时序数据库或物联网数据库 OLAP 分析功能更丰富,列式存储分析性能更好。

  • 支持上千稀疏列,在实际应用中,许多设备的标签字段不一样,可能只有部分设备包含特定标签。VARIANT 利用稀疏列的特性,避免了将稀疏字段拆分为多个独立列,从而提高了存储效率。此外,由于数据在一段时间内往往具有局部性,即某段时间内上报的数据在标签上可能较为密集,但整体来看则相对稀疏。

  • 有更高的压缩率,特别是相较于 String 和 JSON 类型。

结束语

以上就是 Apache Doris 关于半结构化数据 JSON 的解决方案,不论是 Array Map Struct 、JSON 还是 VARIANT 方案,均没有绝对的优劣之分,可通过实际的应用场景,选择最合适的解决方案。

  • Array Map Struct:支持嵌套的固定 Schema,常用于用户行为和画像分析、查询数据湖中 Parquet ORC 等格式数据的场景。
  • JSON:支持嵌套的不固定 Schema,常用于点查和部分分析场景。点查性能好,查询效率至少是 JSON String 的 2 倍。
  • VARIANT :支持嵌套的不固定 Schema,常用于 Log、 Trace、 IoT 等分析场景。相较于 JSON String ,存储空间节省达 64%,冷查询 10 倍以上提升、热查询有 8.4 倍的提升。
Doris开发手记4:倍速性能提升,向量化导入的性能调优实践 正好有Doris社区的小伙伴吐槽向量化的导入性能表现并不是很理想,就借这个机会对之前开发的向量化导入的工作进行了性能调优,取得了不错的优化效果。解决思路也很简单,既然缺页中断是内存没有映射引起的,那这里就尽量复用之前已经使用过的内存,这样,自然也不会引起缺页中断的问题了,对于TLB的缓存访问也有了更高的亲和度。通过替换podarray的内存分配的逻辑之后,效果也很符合预期,通过火焰图进行观察,缺页中断的占比大量的减少,性能上也获得了可观的收益。,记住这个是个缓存),查找对应的虚拟地址到物理地址的映射。 阅读详情

相关推荐

深入解析FDTD Script中的farfieldpolar3d命令:复电场计算与应用

本文深入解析了FDTD仿真中`farfieldpolar3d`命令的核心功能与应用。作为`farfield3d`的复数版本,该命令能计算并返回球坐标系下的复电场矢量,完整保留振幅与相位信息,为光学天线设计、近远场变换及偏振态分析等高级应用提供了关键数据基础。

grafana6viz的博客 286

doris查询性能优化

对比发现scm_employee_salary的hash计算时间,数据合并时间,以及序列化key时间等等都比test_scm_employee_salary的要短,通过前缀索引的调整整体可以提升25%左右的性能。对比发现scm_employee_salary的hash计算时间,数据合并时间,以及序列化key时间等等都比test_scm_employee_salary的要短,通过前缀索引的调整整体可以提升25%左右的性能。这个一种非常明显的空间换时间的优化,他只是提前将sql的执行结果放入一个物化表中。

qq_57106792的博客 4546

从零打造音乐会级特雷门琴:原理、设计与调试全解析

电子乐器的工作原理通常基于信号生成与调制。特雷门琴作为世界上最早的电子乐器之一,其核心原理是利用射频振荡器和电容传感,将演奏者的手势变化转化为音高与音量信号。这种技术通过外差式混频实现音高控制,并利用压控放大器实现细腻的音量动态,其工程价值在于将抽象的空间位置信息精确映射为连续的音频参数。在音乐制作、声音艺术和交互装置等领域,这类技术为创造独特的演奏体验提供了基础。本文聚焦于如何从电路层面实现一台高稳定性的特雷门琴,详细阐述了从LC振荡器设计、天线场形优化到音色混合检波等关键环节,并分享了基于LTspice

weixin_34046298的博客 170

Doris性能优化不要慌,看看这里!

因为Doris这个框架越来越火,行业内已经成为了必不可少的框架,面试当然也是重点考察。Doris性能优化不要慌,分为几个部分掌握回答就好了。关于Doris的优化是一个很大的课题,我们可以从几个方面进行回答。例如:导入、查询、Join优化等等。我们起一个小的系列,专门回答这个问题。我们先从Join优化说起。一、Doris数据划分在介绍Doris中多种Join方式及优化原理之前,先回顾下Doris的数...

微信搜:import_bigdata,大数据领域硬核原创作者 5276

初识YUV,实战NV21格式数据转换为Bitmap

初识YUV,并使用YUV数据生成Bitmap图像一、初识YUV二、采样方式2.1、YUV 4:4:42.2、YUV 4:2:22.2、YUV 4:2:2 一、初识YUV 说到YUV我们就必须先从RGB说起了,如下图所示,请各位把每个色块当成一个像素点。通常一个像素点由RGB(Alpha我们先不考虑)三原色组成。 如下图中第一个像素点,其RGB值分别为(236,102,93),而这三个值就组成了我们看到的 红色 。 然而上图中除了RGB值外,我还标出了每个像素点的YUV的值,YUV的值是怎么来的呢?直接给公

乐翁龙 7125

Windows 11 24H2 外接显卡坞兼容性实测:3步解决USB设备失效

本文详细解析了Windows 11 24H2系统下外接显卡坞导致USB设备失效的问题,并提供了三步终极解决方案:驱动预解压与手动更新、电源管理设置调整、优化的设备连接顺序。通过雷电3接口的兼容性优化,帮助用户解决键盘鼠标卡死等常见问题,提升外接显卡坞的稳定性与性能。

weixin_31714129的博客 578

Doris使用及优化(1.2.6 - 2.0.2 release)

Doris的使用及优化经验,持续更新,欢迎投递。

weixin_43983455的博客 9648

YOLOv8改进 | 融合篇,YOLOv8改进主干网络为MobileNetV4+CBAM注意机制+Powerful-IoU损失函数(2024 最新IOU),全网首发,实现极限涨点

本文将在 YOLOv8 主干中引入 MobileNetV4 轻量化骨干,同时,在检测头引入 CBAM机制注意力机制,并采用 Powerful-IoU 损失函数作为模型的损失函数,其中,MobileNetV4 通过引入通用反向瓶颈(UIB)搜索块和 Mobie MQA 注意力模块创新设计,实现了模型的轻量级化;同时,MobileNetV4 采用了优化的 NAS 策略,通过粗粒度和细粒度搜索相结合的方法,显著提高了搜索效率并改善了模型质量。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 3783

【查询优化】Doris性能优化不要慌,再看看这里!

《Doris性能优化不要慌,再看看这里!- Join优化》《Doris性能优化不要慌,再看看这里!- 导入优化》这篇是第三部分查询优化。OLAP查询对于高并发查询,其核心在于如何平衡有限的系统资源消耗与并发执行带来的高负载。换而言之,需要最大化降低单个 SQL 执行时的 CPU、内存和 IO 开销,其关键在于减少底层数据的 Scan 以及随后的数据计算。Doris能够实现高并发查询的能力主要是通过...

微信搜:import_bigdata,大数据领域硬核原创作者 3251

YOLOv8全网首发:CVPR2026 MixerCSeg | DEGConv方向引导边缘门控,破解细长裂缝检测难题

DEGConv通过方向先验嵌入、边缘增强卷积和动态门控三大机制,针对性解决了YOLO在处理裂缝类细长、多方向、低对比度目标时的特征提取不足问题,显著提升了裂缝检测的精度与鲁棒性。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 514

QGIS编译(跨平台编译)001:Flex、Bison编译(安装)(Windows、Linux、MacOS环境下安装)

QGIS编译;Flex、Bison编译(安装)(Windows、Linux、MacOS环境下安装)

LuckyHanMo的博客 3077

Doris学习笔记之优化

本文记录了Doris优化的一些方法或原则,比如查看QueryProfile、Join优化原则等,并介绍了Bitmap索引和布隆索引,以及优化的原理等

四国棋客 4225

姿态传感器/陀螺仪之LSM6DS3TR-C应用原理图设计

LSM6DS3TR-C是一款由意法半导体(STMicroelectronics)推出的高性能、低功耗的惯性测量单元(IMU),集成了3轴加速度计和3轴陀螺仪,用于测量加速度、角速度以及设备的姿态和运动。

corlin6688的博客 871

Doris性能优化建议

1、jdbc连接中添加参数rewriteBatchedStatements=true,将 JDBC 单条插入优化为批量操作。2、将单条插入攒成批后再插入,可先使用redis的zset存储,,每3秒后取出写入表中,写入失败再写回redis的zset。合理设置 ​分桶数​(Bucket),单个分桶大小建议 ​1-3GB,避免过多小文件导致 Compaction 压力。为减少磁盘IO,可将sys_log_level的值设置为WARN。-- 避免在 FE 中堆积过多的报告任务。-- 为减少磁盘IO。

自律给我自由 1363

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Doris:数组数据类型array使用介绍

【代码】Doris:数组数据类型array使用介绍。

闫玉林的博客 4556

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

doris查询优化-内存调整

doris内存不足错误Memory limit exceeded, 调整参数exec_mem_limit

weixin_42027185的博客 958

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

查询提速 11 倍、资源节省 70%,Apache Doris 在网易日志和时序场景的实践

作者|隐形(邢颖), 网易资深数据库内核工程师编辑整理|SelectDB 技术团队导读:作为网易重要的业务线,灵犀办公和云信针对大规模日志/时序数据处理和分析的挑战,分别构建了灵犀 Eagle 监控平台和云信数据平台。本文将重点介绍。

SelectDB 1817

Apache Doris 2.0 如何实现导入性能提升 2-8 倍

Apache Doris 2.0 进一步增强数据导入能力,性能提升 2-8 倍,加速数据实时处理和分析效率!

SelectDB 3242

Doris的数据类型json和variant区别

如果数据严格符合 JSON 格式且需要复杂查询,选 JSON;如果数据类型多样或结构多变,选 Variant。

主要写大数据集群一线运维和学习工作经验 1174

doris: ARRAY数据类型

doris: ARRAY数据类型

qq_36070104的博客 780

doris:调优流程

doris:调优流程

qq_36070104的博客 1037

Doris之Catalog

Doris Catalog 是 Apache Doris 中用于管理和组织数据的组件。Apache Doris 是一个现代化的MPP(Massively Parallel Processing)数据库,主要用于高效的分析查询。Doris Catalog 在其中起到了至关重要的作用,负责管理数据库、表、视图、分区等元数据。以下是对 Doris Catalog 的详细介绍:

youziguo的专栏 2482

Doris 与 ClickHouse 的深度对比

Doris 与 ClickHouse 的深度对比

u011250186的博客 4836

Doris内存相关配置的优化建议(解决查询时内存不足)

在Doris 3.0.3版本中,遇到大查询或大量数据导出时提示内存不足,即使服务器内存资源充足,可能是由于Doris的内存配置未合理调整。

学亮编程手记 2595

Doris 性能优化总结

摘要:本文系统介绍了Apache Doris数据库性能优化方案,涵盖表设计优化、查询优化、参数调优等核心内容。重点包括合理设计分区/索引/主键,优化SQL编写避免全表扫描,合理配置BE/FE参数,优化数据导入与Compaction策略,利用物化视图提升查询性能,实施资源隔离与监控告警等。针对常见性能瓶颈如慢查询、导入慢等问题提供了具体解决方案,并给出了关键参数调优建议。通过多维度的优化措施,可显著提升Doris集群的整体性能。

onlymscn的博客 928

一.海量数据实时分析-Doris入门和安装

停了一个月又开始写文章啦,因为公司数据量达到了几十亿,老板需要做实时数据分析,报表看板。Apache Doris 由百度大数据部研发(之前叫百度 Palo,2018 年贡献到 Apache 社区后,更名为 Doris ),在百度内部,有超过 200 个产品线在使用,部署机器超过 1000 台,单一业务最大可达到上百 TB。Apache Doris 是一个现代化的 MPP(Massively Parallel Processing,即大规模并行处理)分析型数据库产品。

墨家巨子@俏如来 3248
上一篇: Apache Doris Flink Connector 24.0.0 版本正式发布
下一篇: Apache Doris 2.1.6 版本正式发布
SelectDB技术团队
博客等级 码龄4年 2119粉丝 483原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SelectDB技术团队

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值