Hologress解决数据行转列问题

99 阅读8分钟

此文章来自数据产品部 - 罗启恩

首先说一下什么是数据行转列问题?

  在数据库管理和查询中,数据行转列(Row to Column)是一种常见的挑战。通常,数据行转列问题出现在需要将多行数据聚合为列的场景。例如在图灵的管线任务管理系统中,每一行数据代表一个任务的自定义字段的值,而这些自定义字段是可以动态扩展的,不同任务可能有不同的字段集合。随着业务需求的变化,自定义字段可能会不断增加或修改,导致数据表结构的复杂性和查询难度随之增加。

  在当前的实际场景中,系统需要根据指定的自定义字段,进行任务的筛选、排序和分页查询。为了满足这些需求,通常我们需要将原本的多行数据转换为单行数据形式,列出每个任务的所有自定义字段,形成一个“列式”的结构。这一操作,通常要求将多个行数据合并为每个任务的多个字段值,使查询更加高效和直观。

  然而,在传统的关系型数据库中,处理这类数据行转列的问题通常需要借助复杂的联接(JOIN)或聚合(GROUP BY)操作。这些操作不仅要求数据库在执行查询时对大量的数据进行联合和计算,还可能因为自定义字段数量的变化,导致频繁修改数据库结构或查询逻辑,从而影响系统的扩展性和灵活性。特别是在数据量庞大的情况下,传统数据库在执行这些操作时可能会遭遇性能瓶颈,查询速度慢,资源消耗大,甚至可能导致数据库的超时和崩溃。

  在这种背景下,如何高效地解决数据行转列的问题,尤其是当数据量庞大且自定义字段不断扩展时,成为数据库优化的关键课题。为了应对这一挑战,需要设计更加高效的数据存储和查询方式,减少不必要的计算和查询操作,并确保在处理复杂的数据结构时能够保证较高的性能。   

  

Hologress 怎样解决这个问题?

  Hologress 是一个高效的分布式 OLAP 数据库,专为大数据分析和查询优化而设计。在处理 数据行转列(Row to Column)问题时,Hologress 提供了非常强大的解决方案,尤其是在面对像图灵管线系统这样的场景时,可以大幅度提升查询性能和简化数据存储结构。以下是 Hologress 如何解决你提到的问题的几个关键点:

1. 使用 JSON 格式存储数据

  Hologress 支持将多个自定义字段存储为一个 JSON 字段。这意味着,原本在数据库中需要多行数据来表示一个任务的多个自定义字段的值,可以通过将这些字段聚合为一个 JSON 对象存储在单个字段中。这样做的好处是:

  • 动态扩展:每个任务的自定义字段可以灵活变化,而不需要修改数据库表结构。新的字段只需作为 JSON 对象的一个键值对添加即可。
  • 简化存储结构:不再需要为每个自定义字段单独创建列或行,所有字段都存储在一个 JSON 字段内,减少了数据库表的复杂性。

  例如,每个任务的自定义字段可能会被存储为如下 JSON 对象,这里一条任务记录就同时储存了多达20个自定义字段的内容:

{ "task_id": 1001, "task_value": {"24": {"desc": "", "value": "", "property_id": 24, "property_name": "任务说明", "property_type": 9, "is_selected_person": 2}, "82": {"desc": "AI", "value": "AI", "property_id": 82, "property_name": "类型", "property_type": 5, "is_selected_person": 2}, "469": {"desc": "2024Q2", "value": "2024Q2", "property_id": 469, "property_name": "季度", "property_type": 1, "is_selected_person": 2}, "470": {"desc": "裁决者", "value": "29", "property_id": 470, "property_name": "制作小组", "property_type": 1, "is_selected_person": 2}, "471": {"desc": "Alpha", "value": "11", "property_id": 471, "property_name": "需求大组", "property_type": 1, "is_selected_person": 2}, "472": {"desc": "2024-05-20,2024-05-24", "value": "2024-05-20,2024-05-24", "property_id": 472, "property_name": "周期", "property_type": 11, "is_selected_person": 2}, "474": {"desc": "2024年5月", "value": "2024年5月", "property_id": 474, "property_name": "月份", "property_type": 1, "is_selected_person": 2}, "477": {"desc": "0.5", "value": "0.5", "property_id": 477, "property_name": "验收人天", "property_type": 2, "is_selected_person": 2}, "property_type": 4, "is_selected_person": 2}, "481": {"desc": "/", "value": "/", "property_id": 481, "property_name": "关联宙斯素材编号", "property_type": 2, "is_selected_person": 2}, "482": {"desc": "2024-05-20", "value": "2024-05-20", "property_id": 482, "property_name": "周期开始", "property_type": 8, "is_selected_person": 2}, "483": {"desc": "2024-05-24", "value": "2024-05-24", "property_id": 483, "property_name": "周期结束", "property_type": 8, "is_selected_person": 2}, "484": {"desc": "", "value": "", "property_id": 484, "property_name": "制作方式(填写)", "property_type": 4, "is_selected_person": 2}, "485": {"desc": "原创", "value": "原创", "property_id": 485, "property_name": "制作方式(自动生成)", "property_type": 1, "is_selected_person": 2}, "486": {"desc": "1", "value": "1", "property_id": 486, "property_name": "素材数量", "property_type": 2, "is_selected_person": 2}, "487": {"desc": "1", "value": "1", "property_id": 487, "property_name": "数量(自动生成)", "property_type": 1, "is_selected_person": 2}, "491": {"desc": "否", "value": "否", "property_id": 491, "property_name": "是否额外(填写)", "property_type": 2, "is_selected_person": 2}, "493": {"desc": "否", "value": "否", "property_id": 493, "property_name": "是否额外", "property_type": 4, "is_selected_person": 2}, "10056": {"desc": "否", "value": "否", "property_id": 10056, "property_name": "是否侵权", "property_type": 4, "is_selected_person": 2}, "10073": {"desc": "", "value": "", "property_id": 10073, "property_name": "预计人天", "property_type": 2, "is_selected_person": 2}} }

2. 高效的查询和筛选

  虽然数据被存储在 JSON 字段中,Hologress 提供了强大的查询功能,允许用户对 JSON 字段中的值进行筛选、排序和聚合操作。对于需要对指定的自定义字段进行筛选和排序的查询,Hologress 提供了高效的 JSON 函数和操作符,避免了传统数据库中因联接(JOIN)或聚合(GROUP BY)操作带来的性能问题。

  例如,假设我们需要筛选出 property_id 为 469 且 value 为 2024Q2 的任务,并按 素材数量 排序,可以直接在查询中使用 JSON 路径操作符:

SELECT task_id, task_value->'469'->>'value' as quarter, task_value->'486'->>'value' as asset_num
FROM task
WHERE task_value->'469'->>value = '2024Q2'
ORDER BY task_value->'486'->>value ASC;

3. 优化的分页查询

  由于 Hologress 是基于分布式架构的,它可以有效地处理大量数据,并通过多节点并行处理来加速查询。对于需要分页查询的场景,Hologress 能够在查询中高效地结合 JSON 字段,避免了传统分页查询中可能出现的性能瓶颈。

  例如,假设我们需要按任务的 owner 字段进行分页查询,可以在查询时直接指定分页条件:

SELECT task_id, task_value->'469'->>'value' as quarter, task_value->'486'->>'value' as asset_num
FROM task 
WHERE task_value->'469'->>value = '2024Q2' 
ORDER BY task_value->'486'->>value ASC LIMIT 20 OFFSET 100;

  Hologress 的分布式架构使得分页查询能够在大数据量下保持高效,并且在执行时可以自动优化查询计划,以最大化利用索引和计算资源,提升查询性能。

4. 动态字段支持

  由于 JSON 格式的灵活性,Hologress 使得对于不断变化的自定义字段可以非常便捷地支持动态调整。任务的自定义字段可以在不影响现有数据结构的情况下,随时增加或修改。例如,如果某个任务需要一个新的自定义字段,只需要将其作为 JSON 对象的一部分进行存储,无需修改数据库表的结构。这使得 Hologress 在应对任务中自定义字段的扩展时非常高效和灵活。

5. 高效的分布式查询引擎

  Hologress 的查询引擎是为大数据环境优化的,特别是在处理复杂的 JSON 数据时,其分布式架构能够在多个节点之间并行执行查询,从而大幅度减少查询时间。这对于大规模数据集的查询和分析尤为重要,确保了即使在任务数量巨大、数据量庞大的情况下,查询性能依然优越。   

  

总结

  Hologress 通过其对 JSON 格式的高效存储和查询支持,成功解决了传统关系型数据库在处理数据行转列问题时的性能瓶颈。它能够将多个自定义字段合并为一个 JSON 对象存储,并提供高效的查询、筛选、排序和分页功能,极大地提升了查询的灵活性和执行效率。此外,Hologress 的分布式架构和查询优化确保了在面对大数据量时,依然能保持高效的查询响应速度。对于图灵管线任务这种自定义字段不断变化的场景,Hologress 提供了一个理想的解决方案。