SPC(Secondary Prefix Compression)是PolarDB-X存储引擎中专为非唯一二级索引设计的前缀压缩功能,通过页字典去重存储相同前缀,显著节省索引存储空间。
适用范围
您的实例需满足以下版本要求:
实例系列:标准版或企业版。
引擎版本:MySQL 8.0。
存储节点版本:xcluster8.4.20-20260423及以上版本,即2026-04-23发布的版本及之后版本。
功能简介
SPC在B+Tree的叶子页面上维护一个页字典(Page Dictionary),存储页面内记录的公共前缀。每条记录只存储前缀ID和后缀数据,避免重复存储大量相同的前缀字节。
SPC的核心特性:
页字典最多支持128个不同前缀。
通过前缀去重可显著节省索引存储空间,实际节省比例取决于数据的前缀重复度。
仅适用于非唯一二级索引(唯一索引可使用Panda Index)。
索引格式优先级判断顺序:PANDA > SPC > HIPPO。当多种格式同时开启时,非唯一索引优先使用SPC,唯一索引优先使用PANDA。
开启和关闭SPC
PolarDB-X实例默认关闭SPC能力。若您需要调整SPC能力的开关,可前往PolarDB分布式版控制台,在目标集群的页面的存储层页签中,调整参数opt_index_format_spc_enabled的值。此操作无需重启实例,即时生效。
同时,SPC功能支持以会话粒度控制:
-- 开启
SET SESSION opt_index_format_spc_enabled = ON;
-- 关闭(默认)
SET SESSION opt_index_format_spc_enabled = OFF;此变量控制的是新建索引时是否使用SPC格式,对已有索引无影响。
新建表时,满足条件的非唯一二级索引会自动使用SPC格式:
CREATE TABLE t1 (
id INT NOT NULL PRIMARY KEY,
c1 VARCHAR(200),
c2 VARCHAR(200),
INDEX idx_c1 (c1), -- 自动使用SPC格式
INDEX idx_c1c2 (c1, c2) -- 自动使用SPC格式
) ENGINE=InnoDB;存量索引转换为SPC
对于已有的非SPC索引,可通过以下方式转换为SPC格式(需先确保opt_index_format_spc_enabled = ON):
-- 创建新索引
ALTER TABLE ... ADD INDEX idx_new ...;
-- 更换索引名
ALTER TABLE ... RENAME idx TO idx_old, RENAME INDEX idx_new TO idx;
-- 删除原索引
ALTER TABLE ... DROP INDEX idx_old;系统变量
变量名 | 作用域 | 类型 | 默认值 | 取值范围 | 说明 |
| Session | Boolean | ON | ON|OFF | 控制新建非唯一二级索引时是否启用SPC前缀压缩格式。仅影响新创建的索引,不影响已有索引。 |
| Global | Integer | 30 | 10~100 | DDL构建SPC索引时,前缀压缩的最小数据节省比率(百分比)。值越小越倾向压缩更多页面,值越大只有压缩效果显著的页面才会被编码。 |
| Global | Integer | 2 | 1~100 | DDL构建SPC索引时,每个页面通过前缀压缩进行编码的最大次数,用于防止页面被过度编码导致性能下降。 |
| Global | Integer | 100 | 0~100 | 执行 |
查看SPC索引
通过以下方式查看索引是否使用了SPC格式。
SHOW CREATE TABLE FOR EXPORT
使用
SHOW CREATE TABLE ... FOR EXPORT查看每个索引是否使用SPC格式。其中"spc": "true"表示该索引使用了SPC前缀压缩格式。SHOW CREATE TABLE t_spc_show FOR EXPORT;CREATE TABLE `t_spc_show` ( `id` int NOT NULL, `c1` varchar(200) DEFAULT NULL, `c2` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) /*!80021 SECONDARY_ENGINE_ATTRIBUTE '{"gpp": "false", "panda index": "false", "hippo index": "false", "spc": "false"}' */, KEY `idx_c1` (`c1`) /*!80021 SECONDARY_ENGINE_ATTRIBUTE '{"gpp": "true", "panda index": "false", "hippo index": "false", "spc": "true"}' */, KEY `idx_c1c2` (`c1`,`c2`) /*!80021 SECONDARY_ENGINE_ATTRIBUTE '{"gpp": "true", "panda index": "false", "hippo index": "false", "spc": "true"}' */ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ciINFORMATION_SCHEMA.INNODB_INDEX_STATUS
SELECT SCHEMA_NAME, TABLE_NAME, INDEX_NAME, INDEX_PAGE_TYPE FROM INFORMATION_SCHEMA.INNODB_INDEX_STATUS WHERE TABLE_NAME = 't_spc_demo' AND SCHEMA_NAME = 'test';输出结果中,SPC索引的
INDEX_PAGE_TYPE为SPC_PAGE。INDEX_PAGE_TYPE取值范围说明如下:值
说明
INDEX_PAGE标准B+Tree索引页
SPC_PAGESPC前缀压缩页
PANDA_PAGEPANDA格式页
RTREE_PAGE空间索引页
SDI_PAGE数据字典索引页
统计SPC索引数量
统计当前实例中所有SPC索引(按库分组):
SELECT SCHEMA_NAME, COUNT(*) AS spc_index_count FROM INFORMATION_SCHEMA.INNODB_INDEX_STATUS WHERE INDEX_PAGE_TYPE = 'SPC_PAGE' GROUP BY SCHEMA_NAME;预期返回示例:
+-------------+-----------------+ | SCHEMA_NAME | spc_index_count | +-------------+-----------------+ | test | 3 | +-------------+-----------------+查看某个库下所有使用SPC的表和索引:
SELECT TABLE_NAME, INDEX_NAME FROM INFORMATION_SCHEMA.INNODB_INDEX_STATUS WHERE SCHEMA_NAME = 'test' AND INDEX_PAGE_TYPE = 'SPC_PAGE';预期返回示例:
+--------------+------------+ | TABLE_NAME | INDEX_NAME | +--------------+------------+ | t_spc_demo | idx_c1 | | t_spc_demo | idx_c1c2 | | t_mixed_demo | idx_c2 | +--------------+------------+
压缩统计分析
通过
dbms_spc.analyze_table存储过程,查看SPC索引的详细压缩统计信息:CALL dbms_spc.analyze_table('table_name'); -- 或指定数据库 CALL dbms_spc.analyze_table('db_name.table_name');输出指标说明:
指标
含义
rec_bytes页面上所有记录的总字节数
row_bytes实际行数据的总字节数
comp_recs已压缩的记录数
uncomp_recs未压缩的记录数
dict_bytes页字典区域占用的字节数
dict_slots页字典中的槽位总数
dict_unused_slots页字典中未被任何记录引用的冗余前缀数量
spc_pageSPC格式的页面数
compression ratio压缩比,表示通过SPC可节省的空间比例
采样率控制:您可以通过
innodb_spc_analyze_sample_percentage变量控制分析时的采样比例(默认 100,即采样所有页面):-- 采样 50% 的页面 SET GLOBAL innodb_spc_analyze_sample_percentage = 50;
使用限制
实例版本:由于SPC涉及底层存储结构变动,使用了SPC的实例无法降级至不支持SPC的老版本。
存量索引处理:对于已存在的二级索引,在开启SPC后不会自动转换为SPC索引。您可以通过删除并重建索引的方式进行转换。
创建新索引:
ALTER TABLE ... ADD INDEX idx_new ...;更换索引名:
ALTER TABLE ... RENAME idx TO idx_old, RENAME INDEX idx_new TO idx;删除原索引:
ALTER TABLE ... DROP INDEX idx_old;
不支持SPC的表类型:
压缩表(
ROW_FORMAT=COMPRESSED)临时表(
TEMPORARY TABLE)系统表
非COMPACT或DYNAMIC行格式的表
非16KB页大小(仅支持
innodb_page_size = 16384)
不支持SPC的索引类型:
唯一索引(UNIQUE KEY):使用PANDA格式
聚集索引(PRIMARY KEY):使用标准格式
全文索引(FULLTEXT INDEX)
空间索引(SPATIAL INDEX)
多值索引(Multi-Value Index)
包含虚拟列的索引
DDL行为变化:通常情况下,VARCHAR列的长度扩展只需更新数据字典即可完成,不需要重建表。但如果涉及SPC索引(存量SPC索引的列或新建SPC索引的VARCHAR列发生长度变化),DDL会被强制升级为INPLACE表重建,并产生如下警告:
Warning 1088: Extending column 'X' requires table rebuild because it is part of an SPC index原因是列长度变化会导致SPC索引的页字典容量需要重新计算,而这只能通过重建表来完成。
导出/导入限制:
限制条件
说明
格式必须匹配
源表和目标表的索引格式(SPC与非SPC)必须完全一致。
CFG版本要求
需要CFG V9格式支持,旧版本导出的
.cfg文件无法包含SPC信息。不支持跨版本
旧版本(不支持SPC)导出的表空间无法直接导入为SPC格式。
页字典容量必须一致
源和目标的表结构必须一致,以保证页字典容量计算结果相同。