From 0bd10dbc1e20aaa77c2f9cf86ea8a1fdb2984e47 Mon Sep 17 00:00:00 2001 From: XuJiacheng Date: Tue, 3 Mar 2026 18:22:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E7=88=B6=E8=A1=A8?= =?UTF-8?q?=E7=B4=A2=E5=BC=95=E7=AD=96=E7=95=A5=EF=BC=8C=E7=A1=AE=E4=BF=9D?= =?UTF-8?q?=E4=BB=85=E5=9C=A8=E7=88=B6=E8=A1=A8=E5=88=9B=E5=BB=BA=E7=B4=A2?= =?UTF-8?q?=E5=BC=95=EF=BC=8C=E9=81=BF=E5=85=8D=E5=AD=90=E8=A1=A8=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=B4=A2=E5=BC=95=E7=BB=B4=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bls-rcu-action-backend/scripts/init_db.sql | 4 ++- .../src/db/partitionManager.js | 20 +++++++++++++- .../spec.md | 27 +++++++++++++++++++ .../specs/partition-management/spec.md | 19 +++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 openspec/changes/2026-03-03-parent-index-only-partitions/spec.md create mode 100644 openspec/changes/2026-03-03-parent-index-only-partitions/specs/partition-management/spec.md diff --git a/bls-rcu-action-backend/scripts/init_db.sql b/bls-rcu-action-backend/scripts/init_db.sql index c274a4c..2dfac57 100644 --- a/bls-rcu-action-backend/scripts/init_db.sql +++ b/bls-rcu-action-backend/scripts/init_db.sql @@ -38,7 +38,9 @@ ALTER TABLE rcu_action.rcu_action_events ALTER TABLE rcu_action.rcu_action_events ADD COLUMN IF NOT EXISTS loop_name VARCHAR(255); --- Indexes for performance +-- Indexes for performance (ONLY on parent partitioned table) +-- PostgreSQL will create/attach corresponding child-partition indexes automatically. +-- Do not create duplicated indexes on partition child tables. CREATE INDEX IF NOT EXISTS idx_rcu_action_hotel_id ON rcu_action.rcu_action_events (hotel_id); CREATE INDEX IF NOT EXISTS idx_rcu_action_room_id ON rcu_action.rcu_action_events (room_id); CREATE INDEX IF NOT EXISTS idx_rcu_action_device_id ON rcu_action.rcu_action_events (device_id); diff --git a/bls-rcu-action-backend/src/db/partitionManager.js b/bls-rcu-action-backend/src/db/partitionManager.js index 004d5d6..226f052 100644 --- a/bls-rcu-action-backend/src/db/partitionManager.js +++ b/bls-rcu-action-backend/src/db/partitionManager.js @@ -1,7 +1,24 @@ import { logger } from '../utils/logger.js'; import dbManager from './databaseManager.js'; +const PARENT_TABLE = 'rcu_action.rcu_action_events'; +const PARENT_INDEX_STATEMENTS = [ + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_hotel_id ON rcu_action.rcu_action_events (hotel_id);', + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_room_id ON rcu_action.rcu_action_events (room_id);', + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_device_id ON rcu_action.rcu_action_events (device_id);', + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_direction ON rcu_action.rcu_action_events (direction);', + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_cmd_word ON rcu_action.rcu_action_events (cmd_word);', + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_action_type ON rcu_action.rcu_action_events (action_type);', + 'CREATE INDEX IF NOT EXISTS idx_rcu_action_query_main ON rcu_action.rcu_action_events (hotel_id, room_id, ts_ms DESC);' +]; + class PartitionManager { + async ensureParentIndexes(client) { + for (const sql of PARENT_INDEX_STATEMENTS) { + await client.query(sql); + } + } + /** * Calculate the start and end timestamps (milliseconds) for a given date. * @param {Date} date - The date to calculate for. @@ -33,6 +50,7 @@ class PartitionManager { const client = await dbManager.pool.connect(); try { logger.info(`Starting partition check for the next ${daysAhead} days...`); + await this.ensureParentIndexes(client); const now = new Date(); for (let i = 0; i < daysAhead; i++) { @@ -52,7 +70,7 @@ class PartitionManager { logger.info(`Creating partition ${partitionName} for range [${startMs}, ${endMs})`); const createSql = ` CREATE TABLE IF NOT EXISTS ${partitionName} - PARTITION OF rcu_action.rcu_action_events + PARTITION OF ${PARENT_TABLE} FOR VALUES FROM (${startMs}) TO (${endMs}); `; await client.query(createSql); diff --git a/openspec/changes/2026-03-03-parent-index-only-partitions/spec.md b/openspec/changes/2026-03-03-parent-index-only-partitions/spec.md new file mode 100644 index 0000000..ca2b583 --- /dev/null +++ b/openspec/changes/2026-03-03-parent-index-only-partitions/spec.md @@ -0,0 +1,27 @@ +# Parent-only Index Strategy for Partition Creation + +## 1. 背景 +当前 `rcu_action.rcu_action_events` 使用按天 RANGE 分区。 +本次调整目标是明确并固化索引策略: +- 仅在父表创建索引 +- 分区子表不重复显式创建索引 + +这样可以避免子表重复索引带来的维护成本和潜在冲突,并保持分区创建逻辑简洁。 + +## 2. 策略定义 +1. 父表 `rcu_action.rcu_action_events` 作为索引定义唯一来源。 +2. 分区创建只执行 `CREATE TABLE ... PARTITION OF ...`。 +3. 禁止在分区创建流程中追加 `CREATE INDEX` 到子分区。 +4. 索引初始化保持 `IF NOT EXISTS` 幂等语义。 + +## 3. 实施范围 +- `src/db/partitionManager.js` + - 在分区检查流程中显式确保父表索引存在(幂等)。 + - 创建子分区时仅建分区,不做子表索引创建。 +- `scripts/init_db.sql` + - 明确注释:索引仅建父表,子分区不重复建索引。 + +## 4. 验收标准 +- 分区创建 SQL 不包含任何对子分区的 `CREATE INDEX`。 +- 父表索引可重复执行而不报错(`IF NOT EXISTS`)。 +- 运行初始化和分区预创建后,日志中仅出现父表索引保障与分区建表行为。 diff --git a/openspec/changes/2026-03-03-parent-index-only-partitions/specs/partition-management/spec.md b/openspec/changes/2026-03-03-parent-index-only-partitions/specs/partition-management/spec.md new file mode 100644 index 0000000..21f99e0 --- /dev/null +++ b/openspec/changes/2026-03-03-parent-index-only-partitions/specs/partition-management/spec.md @@ -0,0 +1,19 @@ +## MODIFIED Requirements + +### Requirement: Parent-only index definition for partitioned table +`rcu_action.rcu_action_events` MUST define and maintain query indexes only on the parent partitioned table, and partition child tables MUST NOT run explicit `CREATE INDEX` statements during partition creation. + +#### Scenario: Initialize parent indexes before partition creation +- **WHEN** the service runs database initialization or scheduled partition pre-creation +- **THEN** index creation statements are executed only against `rcu_action.rcu_action_events` +- **AND** statements use `IF NOT EXISTS` to remain idempotent + +#### Scenario: Create a new daily child partition +- **WHEN** a missing partition `rcu_action.rcu_action_events_YYYYMMDD` is created +- **THEN** the SQL only performs `CREATE TABLE ... PARTITION OF ... FOR VALUES ...` +- **AND** no child-specific `CREATE INDEX` statement is executed + +#### Scenario: Prevent duplicate child index maintenance +- **WHEN** partition creation runs repeatedly across deployments +- **THEN** no duplicate child index maintenance logic is introduced in application code +- **AND** parent-table index strategy remains the single source of truth