|
|
@@ -0,0 +1,77 @@
|
|
|
+-- 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;
|