Files
pj_service_cloud/db/20261022_hard_dept_statistics_indexes.sql
2026-10-22 16:17:46 +08:00

89 lines
6.5 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- /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. 核对页面与部门导出全部金额、次数、删除部门及零交易部门结果后再扩大灰度。