折扣卡CPS项目数据库索引优化方案
折扣卡CPS项目数据库索引优化方案折扣卡CPS系统存在订单、核销、分佣、卡密、归因等高频读写表随着订单量上涨经常出现分佣引擎消费慢、核销接口超时、后台报表查询卡顿、对账任务执行耗时过长等问题。很多问题根源在于索引设计不合理、冗余索引过多、联合索引顺序错误、没有区分读写场景。本文结合CPS业务查询特点梳理索引设计原则、核心表优化方案、慢SQL治理、索引维护与风险控制附带相关SQL和业务代码示例。痛点分析第一单字段索引滥用一张表建大量独立索引写入时索引维护开销大卡密批量导入、订单入库变慢。第二联合索引顺序不符合业务查询条件把区分度低的字段放在前面索引失效全表扫描。第三忽略覆盖索引查询大量回表订单列表、分佣明细报表查询耗时高。第四状态字段单独建索引低基数索引效果差比如verify_status、enable这类只有少数枚举值的字段。第五定时对账、补偿任务的查询SQL没有适配索引大表扫描拖垮数据库。第六索引变更没有灰度直接在线DDL锁表高峰期引发服务雪崩。第七多租户场景没有把tenant_id纳入索引不同租户数据混扫隔离性差查询范围过大。整体优化思路遵循业务驱动索引的原则先梳理所有高频SQL再设计联合索引优先满足高频读写链路小程序转链、联盟回调入库、核销提交、分佣引擎消费、定时补偿、后台报表。核心原则多租户场景索引优先带上tenant_id做租户数据隔离联合索引顺序等值条件 范围条件区分度高字段靠前优先打造覆盖索引减少回表枚举状态字段不单独建索引和其他等值字段组合使用定期清理冗余、长期未使用索引大表索引变更使用Online DDL避开业务高峰。核心业务表索引优化方案cps_order CPS订单主表高频查询场景根据租户渠道外部订单号查询回调、核销、对账根据租户openid分页查询用户订单列表补偿任务租户verify_statusis_need_verify扫描核销成功未生成分佣的订单链路追踪根据out_order_no查询订单原不合理设计单独给out_order_no、verify_status、openid分别建立索引。优化索引-- 主键索引id -- 唯一索引租户渠道外部订单号防止重复回调生成重复订单 UNIQUE KEY uk_tenant_channel_outno (tenant_id, channel_code, out_order_no) -- 用户订单查询覆盖基础列表字段 KEY idx_tenant_openid (tenant_id, openid, create_time) -- 核销补偿任务查询索引 KEY idx_tenant_verify_status (tenant_id, verify_status, is_need_verify, create_time)说明verify_status基数低单独索引几乎无效和tenant_id等值条件组合之后才能发挥作用uk同时承担幂等防重和查询加速。cps_commission_template 分佣模板表高频查询租户渠道batch_id匹配模板、租户渠道查询模板列表UNIQUE KEY uk_tenant_channel_batch (tenant_id, channel_code, batch_id) KEY idx_tenant_enable (tenant_id, enable, end_time)匹配模板的Java查询条件就是按tenantId、channelCode、batchId顺序查询和索引顺序保持一致。cps_commission_record 分佣明细表高频场景对账查询、代理商佣金汇总、用户返利记录查询、订单维度查分佣KEY idx_tenant_outno (tenant_id, out_order_no, channel_code) KEY idx_tenant_agent (tenant_id, agent_id, create_time) KEY idx_tenant_openid (tenant_id, openid, create_time)cps_verify_record 核销记录表高频场景核销幂等校验核销单号、根据订单ID查询核销记录UNIQUE KEY uk_verify_no (verify_no) KEY idx_tenant_orderid (tenant_id, order_id)user_card_package 用户卡包表高频场景小程序查询用户有效卡、批次维度统计卡激活数量KEY idx_tenant_openid (tenant_id, openid, status, expire_time) KEY idx_tenant_batch (tenant_id, batch_id, status)cps_link_event 链路追踪事件表时序大表链路表写入量大查询一般按traceId或者out_order_no排查故障按天分表。KEY idx_trace_id (trace_id) KEY idx_tenant_outno (tenant_id, out_order_no)覆盖索引落地示例后台经常查询用户订单列表只需要返回订单号、渠道、核销状态、创建时间SQL示例SELECT out_order_no,channel_code,verify_status,create_time FROM cps_order WHERE tenant_idt001 AND openido123 ORDER BY create_time DESC;索引idx_tenant_openid (tenant_id, openid, create_time)如果把查询字段加入索引做成覆盖索引避免回表KEY idx_tenant_openid_cover (tenant_id, openid, create_time, out_order_no, channel_code, verify_status)覆盖索引适合高频只读报表接口会小幅增加写入成本按需使用不要所有查询都做覆盖索引。慢SQL治理流程开启慢查询日志设置阈值200ms采集业务慢SQL使用explain分析执行计划重点看type、key、rows、Extra排查是否出现Using filesort、Using temporary避免在索引字段上使用函数、隐式类型转换防止索引失效错误示例索引失效// outOrderNo是字符串使用数字对比隐式转换 LambdaQueryWrapperCpsOrder wrapper Wrappers.lambdaQuery(); wrapper.eq(CpsOrder::getOutOrderNo, 123456);正确写法参数类型和字段类型保持一致wrapper.eq(CpsOrder::getOutOrderNo, 123456);定时任务禁止不带时间范围的全状态扫描必须带上create_time时间分片。索引维护与上线风险控制禁止业务高峰期直接执行ALTER TABLE加索引MySQL8.0使用ALTER TABLE … ALGORITHMINPLACE, LOCKNONE;定期查询sys.schema_unused_indexes清理长期未使用的冗余索引新增索引优先在测试环境压测验证写入QPS变化大表新增索引分批灰度先加补偿任务、报表相关索引再优化实时接口索引变更记录文档每个索引备注对应的业务SQL方便后续维护。读写分离配合索引优化可选实时写入回调、核销、分佣走主库后台报表、订单导出、链路查询走从库。报表类查询可以单独在从库增加专用覆盖索引不影响主库写入性能。示例报表统计代理商佣金只在从库建立汇总索引主库不增加。总结折扣卡CPS项目数据库索引优化核心是以业务SQL为依据租户前置、等值优先、控制冗余、低基数字段不独立建索引、区分实时链路和报表查询。索引不是越多越好每一个索引都会增加insert/update/delete的开销CPS订单、核销等高吞吐表尤其敏感。优化之后可以解决核销超时、分佣消费堆积、对账任务跑不动、后台列表卡顿等常见线上问题和之前分佣引擎、核销返利、链路追踪模块配合支撑更大的订单吞吐量。