更新时间:2026-07-30 GMT+08:00
分享

分区选择策略

一级分区选择略

选择合适的分区策略是分区表设计的关键。不同的业务场景具有不同的数据分布特征和查询模式,需要根据实际情况选择最匹配的分区类型。以下分别介绍各类一级分区策略的适用场景和选择建议。

RANGE分区选择策略

选择 RANGE分区(范围分区)最典型的场景是:数据具有连续、有序的范围特征,且查询常围绕该范围进行。

表1 RANGE分区适用场景

场景

示例

优势

时间序列数据

如日志、订单、交易记录,按照日期或时间戳分区。

示例:PARTITION BY RANGE (created_at) 按月或按年分区。

快速删除过期数据(DROP PARTITION)、按时间范围查询时可分区裁剪。

数值范围明确的数据

如价格区间、年龄分段、分数段。

示例:PARTITION BY RANGE (price) 分为 0-100, 100-1000, 1000+。

针对范围查询(BETWEEN、<、>)高效。

需要定期滚动旧数据

业务要求保留最近 N 个月/年的数据,旧数据整分区删除或归档。

示例:要添加新月份的数据,需要将其加载到一个单独的表中,对其进行清理、建立索引,然后使用 EXCHANGE PARTITION 语句将其添加到 RANGE 分区表中,同时原始表保持在线状态。添加新分区后,可以使用 DROP PARTITION 语句删除最后一个月的数据。

便于数据管理和维护,减少存储成本,提高数据管理效率。

分区键与查询条件高度匹配

查询的 WHERE 条件经常包含范围分区键,且结果集中在某几个连续分区内。

示例:分析某年 Q1 的数据,只需扫描对应的 1–3 个分区。

提高查询性能,减少不必要的数据扫描,加快查询速度。

HASH分区选择策略

对于分布规则不明显的数据,并没有明显的范围查找等特征,可以使用HASH分区,将数据分区列的值按照HASH算法打散到不同的分区上,将数据随机分布到各个分区。

  • 使用 HASH 分区的目的
    • 数据分布均匀:分区间数据分布均匀,分区间可以并行访问。
    • 分区修剪:根据分区键使用分区修剪,基于分区键的等值查询开销减小。
    • 避免 I/O 瓶颈:随机分布数据,以避免 I/O 瓶颈。
  • 分区键的选择
    • 唯一或几乎唯一的列或列的组合。
  • 分区数的选择

    2的幂次分区:为每个2的幂次分区创建多个分区和子分区,例如:2、4、8、16、32、64、128等。

LIST分区选择策略

LIST分区根据数据的枚举值进行分区。当分区键是有限、离散的类别值,并且业务查询和运维操作都围绕这些具体值进行时,List 分区是最清晰、高效的选择。它既能对特定分组进行快速访问,又能灵活独立管理每个类别的数据。适合选择LIST分区的场景如下:

  • 枚举或类别字段:分区键是枚举或类别字段,例如 region 取值为 'East', 'West', 'North', 'South'。
  • 特定值过滤:查询常按这些特定值过滤,例如 WHERE region = 'East' 或 WHERE status IN ('paid', 'shipped')。
  • 精确分区裁剪:实现精确的分区裁剪,只扫描相关分区,避免全表扫描。
  • 独立管理:需要按业务类别管理数据,可以对不同分区执行独立的维护操作,如对 'VIP' 用户所在分区优先备份。
  • 值的集合相对稳定:虽然可以后续添加新值到现有分区或新增分区,但频繁变更分区定义(比如每天变化)会增加管理成本。

LIST DEFAULT HASH分区选择策略

当业务数据同时满足以下特征时,推荐您选择LIST DEFAULT HASH分区:

  1. LIST规则无法覆盖所有可能值:
    • 分区键的可能取值非常多,甚至无法预知。
    • 如果为每个值都建立一个 LIST 分区,不仅分区管理复杂,而且在插入新值时必须持续修改表结构,否则会因找不到对应分区而失败。
  2. LIST DEFAULT HASH 通过DEFAULT分区保证系统稳定性和灵活性:

    接收所有未被 LIST 规则匹配的数据,确保系统的稳定性和灵活性。

  3. 数据分布呈现“长尾效应”或“二八原则”:
    • 少数高频值(如头部客户、热门商品)占据了大部分数据量(约 80%),而绝大多数低频值(如普通用户)仅贡献了少量数据(约 20%)。
    • 若将所有低频值都放入一个大的DEFAULT分区,会导致该分区过大,产生新的性能瓶颈。
  4. LIST DEFAULT HASH 实现负载均衡:

    将 DEFAULT 分区进一步拆分为多个HASH子分区,将大量低频数据均匀分布到不同的子分区中,避免数据倾斜,实现负载均衡。

示例

假设您的业务数据中,分区键的可能取值非常多且无法预知,同时数据分布呈现“长尾效应”。例如,您有一个客户表,其中少数头部客户占据了大部分交易量,而大多数普通客户的交易量较少。在这种情况下,使用 LIST DEFAULT HASH 分区策略可以:

  • 通过 LIST 分区规则覆盖已知的头部客户。
  • 使用 DEFAULT 分区接收所有未被 LIST 规则匹配的普通客户数据。
  • 将 DEFAULT 分区进一步拆分为多个 HASH 子分区,确保低频数据均匀分布,避免性能瓶颈。

间隔(INTERVAL)分区选择策略

INTERVAL RANGE分区是RANGE分区的扩展,在数据到达时自动创建间隔分区,不需要再手动创建新分区,方便了RANGE分区维护操作。

  • 插入数据时的行为
    • RANGE分区表:向 RANGE 分区表插入数据时,如果插入的数据超出当前已存在的分区范围,将无法插入,并会返回错误。
    • INTERVAL RANGE分区表:对于INTERVAL RANGE分区表,当新插入的数据超出现有分区的范围时,数据库会自动创建新的分区,根据INTERVAL子句指定的范围来新增分区。
  • 选择策略

    如果您的业务场景满足以下特征,推荐您选择Interval分区。

    • 典型场景:处理时序数据,如系统日志、IoT传感器数据、金融交易流水等。这些场景的数据量巨大且按时间持续增长。
    • 核心诉求:数据按固定时间间隔(如天、月、年) 增长,且有明显的冷热特性(历史数据冷,近期数据热)。
    • 运维目标:希望完全自动化地创建和扩展分区,消除人工干预,确保未来数据写入不会因缺少分区而失败。
  • 示例

    假设分区范围设置为 1 个月,新插入的数据为当前转换点(当前存在的分区的最大边界值)两个月后的数据,将会创建该数据所在月份的分区,以及中间月份的分区。

    例如,您可以创建一个 INTERVAL RANGE 分区表,该表的分区范围为 1 个月,且当前的转换点为 2021 年 9 月 15 日。如果您尝试为 2021年12月10日插入数据,那么将创建2021年9月15日至12月15日所需的3个分区,并将数据插入到相应的分区中。

二级分区选择策略

当单个一级分区内的数据量仍然较大,或业务需要在多个维度上同时管理数据时,可以引入二级分区进行更细粒度的划分。二级分区能够在保留一级分区优势的基础上,进一步优化查询性能、负载均衡和运维管理。以下介绍几种常见的二级分区组合策略及其适用场景。

RANGE-HASH分区选择策略

当您需要按时间(或有序范围)管理大数据量的表,并且单个范围分区内的数据仍需进一步打散以平衡负载、优化等值查询时,建议您选择RANGE-HASH分区。

表2 适用场景

分区

适用场景

一级分区适合RANGE

  • 数据有明确的时间或数值顺序(如 created_at、order_id)。
  • 需要定期滚动删除旧数据(如 DROP PARTITION)。
  • 查询常按该范围进行过滤(如 WHERE created_at BETWEEN ...)。

二级分区适合HASH

  • 在每个范围分区内,数据量巨大(例如,一天的数据量达到几百 GB)。
  • 存在频繁的等值查询或小范围 IN 查询,且查询条件包含另一个字段(如 user_id、device_id)。
  • 希望将同一个范围分区内的数据进一步打散到多个子分区中,以:
    • 避免单个子分区过大,提高维护性(如重建索引、备份)。
    • 分散写入负载,避免高并发写入时的锁竞争或 I/O 热点。
    • 利用并行查询,子分区之间可并行扫描。

示例

  • 场景:大型日志系统
    • 一级分区:按 log_date(天)进行 RANGE 分区,便于删除 90 天前的旧数据。
    • 二级分区:每天写入数亿条日志,查询通常为 WHERE log_date = '2026-05-15' AND user_id = 12345。
      • 问题:若只按天分区,每天的分区仍可能包含几十亿行数据,查询必须扫描整个天的分区,且写入时所有请求争抢同一个分区。
      • 解决方案:在每天的 RANGE 分区内,再按 user_id 进行 Hash 子分区(例如分为64个子分区)。等值查询可精确定位到某一子分区;写入随机分散到不同子分区,降低锁冲突。
  • 场景:订单表
    • 一级分区:按 order_month 进行 RANGE 分区,便于归档历史订单。
    • 二级分区:同一月内的订单按 customer_id 进行 HASH 子分区,避免大客户集中导致单个子分区过大,同时支持快速查询某客户当月的订单。

RANGE-RANGE分区选择策略

RANGE-RANGE分区适用于在多个时间维度上存储与时间相关的数据应用程序,这些应用程序通常不使用某个特定的时间维度来访问数据,而是使用另一个时间维度,有时两者同时使用。

  • 适用场景(两级维度)
    表3 RANGE-RANGE分区适用场景

    分区

    适用场景

    一级分区

    具有自然顺序范围,如时间(年/月/日)、有序 ID 区间。

    二级分区

    同样具有自然顺序范围,如价格区间、分数区间、地理经度/纬度范围、另一个时间(如小时)。

  • 优势
    表4 RANGE-RANGE分区优势

    优势

    描述

    查询模式中两个列都是范围条件

    • 范围条件:查询条件使用范围操作符(如 BETWEEN、<、> 等)。
    • 分区裁剪:RANGE-RANGE 分区对两个范围条件都能进行分区裁剪,性能最优。
    • 对比其他分区策略:
      • Hash 分区:范围查询会扫描所有子分区,造成资源浪费。
      • List 分区:不适合连续范围的查询场景。

    独立维护每个一级分区内的数据

    灵活的二级分区,可以对每个一级分区内的数据按不同的范围区间进行独立维护。

    示例:高价值订单

    当月度一级分区内数据量很大时,可以进一步按价格范围建立子分区,便于对“高价值订单”子分区单独建索引或迁移到高速存储。

  • 示例

    销售数据:

    • 一级分区:按 sale_date 分区(季度)。
    • 二级分区:每个季度内再按 amount 范围分区(如 0-100、100-1000、1000+)。

    查询示例:

    WHERE sale_date BETWEEN Q1 AND Q2 AND amount BETWEEN 200 AND 500;

    先定位到 Q1 和 Q2 的一级分区,再在这些分区内只扫描 amount 对应的子分区,避免全表或全一级分区扫描。

RANGE-LIST分区选择策略

RANGE-LIST分区适用于数据在时间(或有序范围)维度上持续增长,同时每个范围段内的数据又需要按离散类别进行逻辑分组和管理的场景。它结合了RANGE分区的滚动管理能力和List分区的精确分类能力,尤其适合“时间 + 业务类型”的数据模型。

表5 RANGE-LIST分区适用场景

场景

示例

一级分区按范围(RANGE)便于生命周期管理,二级分区按类别(List)便于分组查询/维护

电商订单

  • 一级分区:按 order_date 分区,便于滚动删除旧订单、归档历史数据。
  • 二级分区:按 order_status 分区,便于对特定状态的订单进行维护。

查询示例:

WHERE order_date BETWEEN ... AND order_status IN (...);

上述SQL先定位到月份分区,再精确匹配状态子分区。

一级分区范围内数据量巨大,且不同类别的数据访问热度差异明显

IoT 设备数据

  • 一级分区:按 day RANGE 分区。
  • 二级分区:按 device_type('sensor', 'camera', 'gateway')LIST 分区。
  • 热点设备类型(如 'sensor')可单独放置到快速存储,冷门类型可放到慢速存储。
  • 查询某天、某类设备时,只需扫描对应的子分区。

需要在一级分区范围内对某些特定类别进行完全独立的维护操作

每月订单数据

  • 对 'pending' 状态的子分区设置更严格的锁策略。
  • 对 'completed' 子分区进行压缩。
  • 定期清理 'cancelled' 子分区(TRUNCATE SUBPARTITION 比 DELETE 高效)

二级分区类别的枚举值相对稳定,且与一级分区范围无关

订单状态

  • 无论是哪个月份,订单状态的取值集合都是一样的('pending', 'paid', 'shipped', 'completed', 'cancelled')。
  • 如果二级分区依赖于一级范围(例如不同月份有不同的类别值),则不适用 RANGE-LIST。

相关文档