-- S8-NOTIFICATION-LOG-INDEX-DDL-P2-3 -- Target table: ado_s8_notification_log -- Purpose: 仅用于 S8 notification_log 索引硬化,覆盖以下查询路径: -- A. (channel, created_at) → stuck/orphan dedup 60min cooldown -- query (S8ActiveFlowWatchService.cs 行 67-70 / 175-178)。 -- B. (created_at) → P1.2 S8LogRetentionCleanupJob 的 -- created_at < cutoff 批量清理。 -- -- 设计边界: -- 1. 仅新增 2 个二级索引,不改变任何数据; -- 2. 不改字段、不改字段类型、不改 nullable、不改表结构; -- 3. 不执行 DML(INSERT/UPDATE/DELETE); -- 4. 不执行 DROP TABLE / TRUNCATE / ALTER COLUMN / MODIFY COLUMN; -- 5. 执行前必须先跑下方 pre-check SELECT,命中(>0 行)即跳过对应 CREATE INDEX; -- 6. 索引名必须与 AdoS8NotificationLog 实体 [SugarIndex] 注解完全一致: -- - idx_s8_notif_channel_time (Channel, CreatedAt) -- - idx_s8_notif_created_at (CreatedAt) -- 避免 EnableInitTable=true 时 CodeFirst 与手工 DDL 冲突; -- 7. 使用 ALGORITHM=INPLACE, LOCK=NONE,与 InnoDB ONLINE DDL 一致, -- 避免对在线写入产生表锁; -- 8. 建议低峰执行;执行时机由数据负责人在阶段 2 决定。 -- -- 不在本脚本范围: -- - 暂不包含 (tenant_id, factory_id, channel, created_at) 复合索引(候选 C, -- 留待后续聚合/API 瓶颈出现后再评估); -- - 不在 ado_s8_notification_log 上做任何 DROP;如需回滚,请使用同目录的 -- 20260531_s8_notification_log_indexes_rollback.sql。 -- -- Idempotency: -- MySQL 8 不支持 CREATE INDEX IF NOT EXISTS。如果索引已存在重跑会抛 -- "Duplicate key name",属安全错误,先跑 pre-check 可避免。 -- ========================================================================= -- Pre-check (run first; non-destructive; expect 0 rows when index absent) -- ========================================================================= -- Pre-check A: idx_s8_notif_channel_time SELECT COUNT(*) AS exists_channel_time FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ado_s8_notification_log' AND INDEX_NAME = 'idx_s8_notif_channel_time'; -- Pre-check B: idx_s8_notif_created_at SELECT COUNT(*) AS exists_created_at FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ado_s8_notification_log' AND INDEX_NAME = 'idx_s8_notif_created_at'; -- ========================================================================= -- Index creation (run each only when its pre-check returned 0) -- ========================================================================= -- Index A: stuck/orphan dedup 60min cooldown (channel + created_at) CREATE INDEX idx_s8_notif_channel_time ON ado_s8_notification_log (channel, created_at) ALGORITHM=INPLACE LOCK=NONE; -- Index B: retention cleanup (created_at < cutoff) CREATE INDEX idx_s8_notif_created_at ON ado_s8_notification_log (created_at) ALGORITHM=INPLACE LOCK=NONE; -- ========================================================================= -- Post-check (run after creation; expect 2 rows total, one per index) -- ========================================================================= SELECT INDEX_NAME, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS cols FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ado_s8_notification_log' AND INDEX_NAME IN ( 'idx_s8_notif_channel_time', 'idx_s8_notif_created_at' ) GROUP BY INDEX_NAME;