PolarDB for PostgreSQLPolarDB for PostgreSQL
  • 架构简介
  • 快速部署
  • 进阶部署
  • 共享存储设备的准备

    • 阿里云 ECS + ESSD 云盘存储
  • 文件系统的准备

    • 格式化并挂载 PFS
  • 部署 PolarDB-PG 数据库

    • 基于单机文件系统部署
    • 基于 PFS 文件系统部署
  • 更多部署方式

    • 购买商业版
  • 日常运维

    • 备份恢复
    • 共享存储在线扩容
    • 计算节点扩缩容
    • Replica 节点在线 Promote
  • 问题诊断

    • CPU 使用率高的排查方法
  • 性能测试

    • TPC-C 测试
    • TPC-H 测试
  • 功能分类

    • 高性能
    • 高可用
    • 安全
    • 弹性跨机并行查询(ePQ)
    • 第三方插件
  • PolarDB for PostgreSQL

    • 特性总览
    • HTAP 架构详解
    • 缓冲区管理
    • DDL 同步
    • LogIndex
  • PostgreSQL

    • ANALYZE 源码解读
    • Sequence 使用、原理全面解析
  • 基于 Docker 容器开发
  • 定制开发环境
  • 贡献代码
  • 贡献文档
  • 编码风格
  • 问题报告
  • English
  • 简体中文
GitHub
  • 架构简介
  • 快速部署
  • 进阶部署
  • 共享存储设备的准备

    • 阿里云 ECS + ESSD 云盘存储
  • 文件系统的准备

    • 格式化并挂载 PFS
  • 部署 PolarDB-PG 数据库

    • 基于单机文件系统部署
    • 基于 PFS 文件系统部署
  • 更多部署方式

    • 购买商业版
  • 日常运维

    • 备份恢复
    • 共享存储在线扩容
    • 计算节点扩缩容
    • Replica 节点在线 Promote
  • 问题诊断

    • CPU 使用率高的排查方法
  • 性能测试

    • TPC-C 测试
    • TPC-H 测试
  • 功能分类

    • 高性能
    • 高可用
    • 安全
    • 弹性跨机并行查询(ePQ)
    • 第三方插件
  • PolarDB for PostgreSQL

    • 特性总览
    • HTAP 架构详解
    • 缓冲区管理
    • DDL 同步
    • LogIndex
  • PostgreSQL

    • ANALYZE 源码解读
    • Sequence 使用、原理全面解析
  • 基于 Docker 容器开发
  • 定制开发环境
  • 贡献代码
  • 贡献文档
  • 编码风格
  • 问题报告
  • English
  • 简体中文
GitHub
  • 自研功能
    • 功能分类

      • 高性能
        • 预读 / 预扩展
        • 表大小缓存
        • Shared Server
      • 高可用
        • 只读节点 Online Promote
        • WAL 日志并行回放
        • DataMax 日志节点
        • Resource Manager
        • 闪回表和闪回日志
      • 安全
        • TDE 透明数据加密
        • polar_login_history 会话访问历史
      • 弹性跨机并行查询(ePQ)
        • ePQ 执行计划查看与分析
        • ePQ 计算节点范围选择与并行度控制
        • ePQ 支持分区表查询
        • ePQ 支持创建 B-Tree 索引并行加速
        • 集群拓扑视图
        • 自适应扫描
        • 并行 INSERT
        • ePQ 支持创建/刷新物化视图并行加速和批量写入
      • 第三方插件
        • pgvector
        • smlar

ePQ 支持创建 B-Tree 索引并行加速

V11 / v1.1.15-

棠羽

2023/09/20

20 min

  • 背景
  • 使用方法
    • 数据准备
    • 创建索引
    • 并发创建索引
  • 使用限制

背景

在使用 PostgreSQL 时,如果想要在一张表中查询符合某个条件的行,默认情况下需要扫描整张表的数据,然后对每一行数据依次判断过滤条件。如果符合条件的行数非常少,而表的数据总量非常大,这显然是一个非常低效的操作。与阅读书籍类似,想要阅读某个特定的章节时,读者通常会通过书籍开头处的索引查询到对应章节的页码,然后直接从指定的页码开始阅读;在数据库中,通常会对被频繁查找的列创建索引,以避免进行开销极大的全表扫描:通过索引可以精确定位到被查找的数据位于哪些数据页面上。

PostgreSQL 支持创建多种类型的索引,其中使用得最多的是 B-Tree 索引,也是 PostgreSQL 默认创建的索引类型。在一张数据量较大的表上创建索引是一件非常耗时的事,因为其中涉及到的工作包含:

  1. 顺序扫描表中的每一行数据
  2. 根据要创建索引的列值(Scan Key)顺序,对每行数据在表中的物理位置进行排序
  3. 构建索引元组,按 B-Tree 的结构组织并写入索引页面

PostgreSQL 支持并行(多进程扫描/排序)和并发(不阻塞 DML)创建索引,但只能在创建索引的过程中使用单个计算节点的资源。

PolarDB-PG 的 ePQ 弹性跨机并行查询特性支持对 B-Tree 类型的索引创建进行加速。ePQ 能够利用多个计算节点的 I/O 带宽并行扫描全表数据,并利用多个计算节点的 CPU 和内存资源对每行数据在表中的物理位置按索引列值进行排序,构建索引元组。最终,将有序的索引元组归并到创建索引的进程中,写入索引页面,完成索引的创建。

使用方法

数据准备

创建一张包含三个列,数据量为 1000000 行的表:

CREATE TABLE t (id INT, age INT, msg TEXT);

INSERT INTO t
SELECT
    random() * 1000000,
    random() * 10000,
    md5(random()::text)
FROM generate_series(1, 1000000);

创建索引

使用 ePQ 创建索引需要以下三个步骤:

  1. 设置参数 polar_enable_px 为 ON,打开 ePQ 的开关
  2. 按需设置参数 polar_px_dop_per_node 调整查询并行度
  3. 在创建索引时显式声明 px_build 属性为 ON
SET polar_enable_px TO ON;
SET polar_px_dop_per_node TO 8;
CREATE INDEX t_idx1 ON t(id, msg) WITH(px_build = ON);

在创建索引的过程中,数据库会对正在创建索引的表施加 ShareLock 锁。这个级别的锁将会阻塞其它进程对表的 DML 操作(INSERT / UPDATE / DELETE)。

并发创建索引

类似地,ePQ 支持并发创建索引,只需要在 CREATE INDEX 后加上 CONCURRENTLY 关键字即可:

SET polar_enable_px TO ON;
SET polar_px_dop_per_node TO 8;
CREATE INDEX CONCURRENTLY t_idx2 ON t(id, msg) WITH(px_build = ON);

在创建索引的过程中,数据库会对正在创建索引的表施加 ShareUpdateExclusiveLock 锁。这个级别的锁将不会阻塞其它进程对表的 DML 操作。

使用限制

ePQ 加速创建索引暂不支持以下场景:

  • 创建 UNIQUE 索引
  • 创建索引时附带 INCLUDING 列
  • 创建索引时指定 TABLESPACE
  • 创建索引时带有 WHERE 而成为部分索引(Partial Index)
在 GitHub 上编辑此页
上次更新:
贡献者: Shijun.Zhou
Prev
ePQ 支持分区表查询
Next
集群拓扑视图