perf: IoT 卡 30M 行分页查询优化(P95 17.9s → <500ms)
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m6s

- 新增 is_standalone 物化列 + 触发器自动维护(迁移 056)
- 并行查询拆分:多店铺 IN 查询拆为 per-shop goroutine 并行 Index Scan
- 两阶段延迟 Join:深度分页(page≥50)走覆盖索引 Index Only Scan 取 ID 再回表
- COUNT 缓存:per-shop 并行 COUNT + Redis 30 分钟 TTL
- 索引优化:删除有害全局索引、新增 partial composite indexes(迁移 057/058)
- ICCID 模糊搜索路径隔离:trigram GIN 索引走独立查询路径
- 慢查询阈值从 100ms 调整为 500ms
- 新增 30M 测试数据种子脚本和 benchmark 工具
This commit is contained in:
2026-02-24 16:23:02 +08:00
parent c665f32976
commit f32d32cd36
20 changed files with 2705 additions and 50 deletions

View File

@@ -0,0 +1,98 @@
-- 创建遗留表(原由 GORM AutoMigrate 自动创建,迁移文件中缺失)
-- 这 4 张表是项目最早期通过 AutoMigrate 创建的,后续迁移 000001-000010 依赖它们的存在
-- 本迁移还原 AutoMigrate 创建时的原始结构(不含后续 ALTER 添加的字段)
-- ============================================================
-- 1. 账号表tb_account
-- 注意:此处包含 parent_id 字段,该字段在 000002 迁移中被 DROP
-- 注意enterprise_id 由 000002 添加is_primary 由 000010 添加,此处不包含
-- ============================================================
CREATE TABLE IF NOT EXISTS tb_account (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE,
deleted_at TIMESTAMP WITH TIME ZONE,
creator BIGINT NOT NULL,
updater BIGINT NOT NULL,
username VARCHAR(50) NOT NULL,
phone VARCHAR(20) NOT NULL,
password VARCHAR(255) NOT NULL,
user_type BIGINT NOT NULL,
shop_id BIGINT,
parent_id BIGINT,
status BIGINT NOT NULL DEFAULT 1
);
-- 索引(与 GORM AutoMigrate 生成的一致)
CREATE UNIQUE INDEX IF NOT EXISTS idx_account_username ON tb_account(username) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_account_phone ON tb_account(phone) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_tb_account_user_type ON tb_account(user_type);
CREATE INDEX IF NOT EXISTS idx_tb_account_shop_id ON tb_account(shop_id);
CREATE INDEX IF NOT EXISTS idx_tb_account_deleted_at ON tb_account(deleted_at);
-- ============================================================
-- 2. 权限表tb_permission
-- 注意platform 由 000003 添加available_for_role_types 由 000009 添加,此处不包含
-- ============================================================
CREATE TABLE IF NOT EXISTS tb_permission (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE,
deleted_at TIMESTAMP WITH TIME ZONE,
creator BIGINT NOT NULL,
updater BIGINT NOT NULL,
perm_name VARCHAR(50) NOT NULL,
perm_code VARCHAR(100) NOT NULL,
perm_type BIGINT NOT NULL,
url VARCHAR(255),
parent_id BIGINT,
sort BIGINT NOT NULL DEFAULT 0,
status BIGINT NOT NULL DEFAULT 1
);
-- 索引
CREATE UNIQUE INDEX IF NOT EXISTS idx_permission_code ON tb_permission(perm_code) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_tb_permission_perm_type ON tb_permission(perm_type);
CREATE INDEX IF NOT EXISTS idx_tb_permission_parent_id ON tb_permission(parent_id);
CREATE INDEX IF NOT EXISTS idx_tb_permission_deleted_at ON tb_permission(deleted_at);
-- ============================================================
-- 3. 角色表tb_role
-- ============================================================
CREATE TABLE IF NOT EXISTS tb_role (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE,
deleted_at TIMESTAMP WITH TIME ZONE,
creator BIGINT NOT NULL,
updater BIGINT NOT NULL,
role_name VARCHAR(50) NOT NULL,
role_desc VARCHAR(255),
role_type BIGINT NOT NULL,
status BIGINT NOT NULL DEFAULT 1
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_tb_role_role_type ON tb_role(role_type);
CREATE INDEX IF NOT EXISTS idx_tb_role_deleted_at ON tb_role(deleted_at);
-- ============================================================
-- 4. 角色权限关联表tb_role_permission
-- ============================================================
CREATE TABLE IF NOT EXISTS tb_role_permission (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE,
deleted_at TIMESTAMP WITH TIME ZONE,
creator BIGINT NOT NULL,
updater BIGINT NOT NULL,
role_id BIGINT NOT NULL,
perm_id BIGINT NOT NULL,
status BIGINT NOT NULL DEFAULT 1
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_tb_role_permission_role_id ON tb_role_permission(role_id);
CREATE INDEX IF NOT EXISTS idx_tb_role_permission_perm_id ON tb_role_permission(perm_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_role_permission_unique ON tb_role_permission(role_id, perm_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_tb_role_permission_deleted_at ON tb_role_permission(deleted_at);