20260531_s8_notification_log_indexes.sql 3.5 KB

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