-- /hard/hard-total/page-list-dept 与部门导出配套索引;目标:PolarDB MySQL 8。 -- 本脚本只读取索引元数据并按需创建索引,不写业务数据,不删除或替换现有索引。 -- 索引名称不是等效判断依据:已有其他名称的可见 BTREE 索引满足条件时同样跳过。 -- 若目标名称已被不同定义占用且不存在等效索引,CREATE INDEX 会报错并停止该条; -- 应先核对 SHOW INDEX,不能把不同定义的同名索引当作本次所需索引。 -- 大表低峰逐条执行。INPLACE/LOCK=NONE 仍需短暂元数据锁,应先排查长事务, -- 核对实际 PolarDB 小版本的在线 DDL 支持、可用空间和复制延迟,不并行建大表索引。 -- PolarDB DDL:https://help.aliyun.com/zh/polardb/polardb-for-mysql/user-guide/support-for-ddl-in-polardb-mysql -- -- 代码发布依赖:先发布 Wallet 的 /wallet-transaction/department-statistics 新内部接口, -- 再发布 Hardware。Hardware 新支付聚合直接读取 pjcloudx_wallet.wallet_transaction, -- 两库须位于同一实例,Hardware 应用数据库账号须具备该表 SELECT 权限。 -- 测试使用的 root 账号权限不能作为生产应用账号权限的验证依据。 -- 一、订单按创建时间做范围覆盖扫描。 -- 等效索引须以前三列 tenant_id,del_flag,create_time 按此顺序开头,包含以下全部七列, -- 所有显式索引列均为完整列(无前缀截断),且索引可见、类型为 BTREE。 -- 后续覆盖列允许不同顺序或额外列;只有前三列的窄索引不能替代本次覆盖索引。 SET @hard_dept_order_cover_exists = ( SELECT COUNT(*) FROM ( SELECT INDEX_NAME, SUM(SEQ_IN_INDEX = 1 AND COLUMN_NAME = 'tenant_id') AS tenant_first, SUM(SEQ_IN_INDEX = 2 AND COLUMN_NAME = 'del_flag') AS deletion_second, SUM(SEQ_IN_INDEX = 3 AND COLUMN_NAME = 'create_time') AS created_third, COUNT(DISTINCT CASE WHEN COLUMN_NAME IN ('tenant_id','del_flag','create_time','order_status','wallet_id','user_dept_id','pay_price') THEN COLUMN_NAME END) AS covered_columns, SUM(SUB_PART IS NOT NULL) AS prefix_columns FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_order' AND INDEX_TYPE = 'BTREE' AND IS_VISIBLE = 'YES' GROUP BY INDEX_NAME ) existing_indexes WHERE tenant_first = 1 AND deletion_second = 1 AND created_third = 1 AND covered_columns = 7 AND prefix_columns = 0 ); SET @hard_dept_order_cover_ddl = IF(@hard_dept_order_cover_exists = 0, 'CREATE INDEX idx_hard_order_dept_ct_cover ON pjcloudx_hardware.hard_order (tenant_id,del_flag,create_time,order_status,wallet_id,user_dept_id,pay_price) ALGORITHM=INPLACE LOCK=NONE', 'SELECT ''部门订单创建时间覆盖索引已存在,跳过'' AS message'); PREPARE hard_dept_order_cover_statement FROM @hard_dept_order_cover_ddl; EXECUTE hard_dept_order_cover_statement; DEALLOCATE PREPARE hard_dept_order_cover_statement; -- 二、按租户和业务编号定位少量支付流水,再校验钱包、业务类型、删除状态和部门,取最新有效记录。 -- 复用 20261022_wallet_rule_transaction_page_index.sql 中的 idx_wt_tenant_bizid_type, -- 不为部门报表再创建另一条更宽的同类索引。 -- 任何以完整 tenant_id,biz_id 两列开头的可见 BTREE 索引均视为可复用;后续列可有前缀。 -- biz_type 是 TINYTEXT,新增候选必须写 biz_type(8),该候选不是完整覆盖索引。 -- biz_id 高度选择性,用索引定位后执行精确字节匹配及最新有效快照筛选。 SET @hard_dept_wallet_biz_lookup_exists = ( SELECT COUNT(*) FROM ( SELECT INDEX_NAME, SUM(SEQ_IN_INDEX = 1 AND COLUMN_NAME = 'tenant_id' AND SUB_PART IS NULL) AS tenant_first, SUM(SEQ_IN_INDEX = 2 AND COLUMN_NAME = 'biz_id' AND SUB_PART IS NULL) AS complete_biz_second FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = 'pjcloudx_wallet' AND TABLE_NAME = 'wallet_transaction' AND INDEX_TYPE = 'BTREE' AND IS_VISIBLE = 'YES' GROUP BY INDEX_NAME ) existing_indexes WHERE tenant_first = 1 AND complete_biz_second = 1 ); SET @hard_dept_wallet_biz_lookup_ddl = IF(@hard_dept_wallet_biz_lookup_exists = 0, 'CREATE INDEX idx_wt_tenant_bizid_type ON pjcloudx_wallet.wallet_transaction (tenant_id,biz_id,biz_type(8)) ALGORITHM=INPLACE LOCK=NONE', 'SELECT ''钱包租户业务编号索引已存在,复用并跳过'' AS message'); PREPARE hard_dept_wallet_biz_lookup_statement FROM @hard_dept_wallet_biz_lookup_ddl; EXECUTE hard_dept_wallet_biz_lookup_statement; DEALLOCATE PREPARE hard_dept_wallet_biz_lookup_statement; -- 三、钱包六类流水合并统计先复用既有 idx_wallet_tx_tenant_del_biz_ct_uid -- (tenant_id,del_flag,biz_type(8),create_time,user_id),本脚本不额外创建宽聚合索引。 -- 该索引来自 20261004_wallet_transaction_page_index.sql / 20260826 索引脚本, -- 不是包含 dept_id、price 的覆盖索引。日期范围汇总使用 INDEX 优化器提示建议采用该索引, -- 防止业务号索引仅按 tenant_id 扫描整个租户。请核实同名索引存在且定义正确; -- 提示要求引擎支持 MySQL 8.0.20+ 的 INDEX hint,未知提示或缺失索引时会忽略并回退, -- 因此发布须以实际 PolarDB 的 EXPLAIN 和 SHOW WARNINGS 验收,不能仅凭 SQL 成功。 -- 定向钱包或没有合法日期范围时不加此提示。 -- 对大批导入/临时造数后索引统计失真,应刷新统计后再核对计划; -- 本脚本不自动对业务大表执行 ANALYZE,生产按维护窗口和实际统计情况处理。 -- -- 发布验收使用真实租户、日期、部门包含/排除及钱包类型参数执行 EXPLAIN ANALYZE: -- 1. 订单时间范围扫描应能使用创建时间覆盖索引,避免逐条回表读取订单字段。 -- 2. 历史流水应通过 tenant_id,biz_id 等值定位,不能逐单扫描全部钱包流水; -- 源 SQL 保留普通 biz_id 字符串等值,额外 BINARY 等值只作精确匹配校验。 -- 3. 检查 NO_MERGE 派生表及相关子查询实际 loops,确认历史部门不会被重复求值。 -- 4. 钱包合并统计只执行一次;定向钱包或其他高选择性条件允许选择更合适的既有索引。 -- 5. 核对页面与部门导出全部金额、次数、删除部门及零交易部门结果后再扩大灰度。