-- 1.0.321.sql  S2 排程性能 L1：齐套检查/BOM 展开热点路径补齐二级索引。
--   背景：EXPLAIN ANALYZE 实测 ic_bom_child 子件查询扫 59,799+22,108 行、服务端 103ms；
--         InvMaster 库存查询扫 18,368 行、17.9ms。二者均为全表扫描（无可用索引）。
--   本脚本只建【非唯一】二级索引 + 一个主键，不改字段类型/可空性，不增删改任何业务数据，
--   不删除任何现有索引。因此不存在数据冲突导致失败的可能，无需前置去重。
--   索引列依据见 doc/plan/S2排程性能-L1索引体系执行任务书.md §2.4（逐条对应实际查询条件）。
-- ============================================================================

-- ========== 〇、通用幂等宏说明 ==========
-- 每个索引统一走：查 information_schema.STATISTICS 判是否已存在 -> 不存在才 ADD。
-- 重复执行本脚本不会报错，也不会重复创建。

-- ========== 一、ic_bom_child（59,799 行，当前零索引含主键） ==========
-- 1.1 主键。已实证 Id 全部唯一且非空（59799/59799，null=0）；
--     且全仓库无任何应用侧 INSERT 写该表（仅 MaterialRequirementCalculator 的 SELECT），
--     不会因新主键产生重复键失败。
SET @has_pk := (SELECT COUNT(*) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ic_bom_child' AND INDEX_NAME = 'PRIMARY');
SET @sql := IF(@has_pk = 0,
    'ALTER TABLE ic_bom_child ADD PRIMARY KEY (Id)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- 1.2 主查询路径：WHERE bom_id=? AND tenant_id=? AND IsDeleted=0
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ic_bom_child'
      AND INDEX_NAME = 'idx_ic_bom_child_tenant_bom');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE ic_bom_child ADD INDEX idx_ic_bom_child_tenant_bom (tenant_id, bom_id, IsDeleted)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- 1.3 反查父阶 / 按物料查用量
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ic_bom_child'
      AND INDEX_NAME = 'idx_ic_bom_child_tenant_item');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE ic_bom_child ADD INDEX idx_ic_bom_child_tenant_item (tenant_id, item_number)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 二、ItemMaster（22,108 行） ==========
-- 现有 uk_ItemMaster_factory_item (tenant_id, factory_ref_id, ItemNum) 因中间缺 factory_ref_id
-- 无法服务 BOM 子件关联，补 (tenant_id, ItemNum)。不动现有唯一索引。
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ItemMaster'
      AND INDEX_NAME = 'idx_ItemMaster_tenant_item');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE ItemMaster ADD INDEX idx_ItemMaster_tenant_item (tenant_id, ItemNum)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 三、ic_bom（5,431 行） ==========
-- 3.1 ResolveBomIdByItemAsync：WHERE tenant_id=? AND IsDeleted=0 AND item_number=?
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ic_bom'
      AND INDEX_NAME = 'idx_ic_bom_tenant_item');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE ic_bom ADD INDEX idx_ic_bom_tenant_item (tenant_id, item_number, IsDeleted)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- 3.2 ResolveBomIdAsync 的 bom_number 分支
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ic_bom'
      AND INDEX_NAME = 'idx_ic_bom_tenant_bomnum');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE ic_bom ADD INDEX idx_ic_bom_tenant_bomnum (tenant_id, bom_number)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 四、InvMaster（18,368 行） ==========
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'InvMaster'
      AND INDEX_NAME = 'idx_InvMaster_tenant_item');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE InvMaster ADD INDEX idx_InvMaster_tenant_item (tenant_id, ItemNum)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 五、PurOrdDetail（95 行，为将来增长预留） ==========
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'PurOrdDetail'
      AND INDEX_NAME = 'idx_PurOrdDetail_item_ord');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE PurOrdDetail ADD INDEX idx_PurOrdDetail_item_ord (ItemNum, PurOrdRecID)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 六、ic_item_stockoccupy（497 行；排程起始 DELETE + 占用汇总） ==========
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ic_item_stockoccupy'
      AND INDEX_NAME = 'idx_ic_item_stockoccupy_tenant_bang');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE ic_item_stockoccupy ADD INDEX idx_ic_item_stockoccupy_tenant_bang (tenant_id, bang_id, IsDeleted)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 七、b_bom_child_examine（8,679 行，齐套结果明细） ==========
-- examine_id 必须最左：ResourceCheckResultWriter 的 UPDATE 只带 examine_id、不带 tenant_id。
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'b_bom_child_examine'
      AND INDEX_NAME = 'idx_b_bom_child_examine_examine');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE b_bom_child_examine ADD INDEX idx_b_bom_child_examine_examine (examine_id, tenant_id, is_use)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 八、b_examine_result（279 行，齐套结果头） ==========
SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'b_examine_result'
      AND INDEX_NAME = 'idx_b_examine_result_tenant_entry');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE b_examine_result ADD INDEX idx_b_examine_result_tenant_entry (tenant_id, sentry_id, IsDeleted)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

SET @has_ix := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'b_examine_result'
      AND INDEX_NAME = 'idx_b_examine_result_tenant_morder');
SET @sql := IF(@has_ix = 0,
    'ALTER TABLE b_examine_result ADD INDEX idx_b_examine_result_tenant_morder (tenant_id, morder_no)', 'DO 0');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

-- ========== 九、刷新统计信息，让优化器立刻用上新索引 ==========
ANALYZE TABLE ic_bom_child;
ANALYZE TABLE ItemMaster;
ANALYZE TABLE ic_bom;
ANALYZE TABLE InvMaster;
ANALYZE TABLE PurOrdDetail;
ANALYZE TABLE ic_item_stockoccupy;
ANALYZE TABLE b_bom_child_examine;
ANALYZE TABLE b_examine_result;

-- ============================================================================
-- 回滚 SQL（本脚本只加不减，回滚即逐条 DROP，不会丢任何数据）：
--   ALTER TABLE ic_bom_child        DROP INDEX idx_ic_bom_child_tenant_bom;
--   ALTER TABLE ic_bom_child        DROP INDEX idx_ic_bom_child_tenant_item;
--   ALTER TABLE ic_bom_child        DROP PRIMARY KEY;
--   ALTER TABLE ItemMaster          DROP INDEX idx_ItemMaster_tenant_item;
--   ALTER TABLE ic_bom              DROP INDEX idx_ic_bom_tenant_item;
--   ALTER TABLE ic_bom              DROP INDEX idx_ic_bom_tenant_bomnum;
--   ALTER TABLE InvMaster           DROP INDEX idx_InvMaster_tenant_item;
--   ALTER TABLE PurOrdDetail        DROP INDEX idx_PurOrdDetail_item_ord;
--   ALTER TABLE ic_item_stockoccupy DROP INDEX idx_ic_item_stockoccupy_tenant_bang;
--   ALTER TABLE b_bom_child_examine DROP INDEX idx_b_bom_child_examine_examine;
--   ALTER TABLE b_examine_result    DROP INDEX idx_b_examine_result_tenant_entry;
--   ALTER TABLE b_examine_result    DROP INDEX idx_b_examine_result_tenant_morder;
-- 回滚后还需把 sys_db_migration_log 中 version='1.0.321' 的行删除，脚本才会重跑。
-- ============================================================================
