已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
【背景】 15 年 DBA,最近在给一套结算系统(MySQL 8.0.32 / InnoDB,单主 16C64G,buffer_pool 40G)做索引治理。核心表 t_settle_bill 约 6500 万行、单表 41GB,写 QPS 约 1800(以 INSERT + 状态 UPDATE 为主),读 QPS 约 900。
一条高频查询是「查某商户某账期内按金额倒序的账单」:
SELECT id, bill_no, amount, status, gmt_create
FROM t_settle_bill
WHERE merchant_id = ? AND gmt_create BETWEEN ? AND ?
ORDER BY amount DESC
LIMIT 20;
现有索引是 idx_merchant_create (merchant_id, gmt_create),EXPLAIN 显示 type=range、key=idx_merchant_create、Extra=Using filesort。单商户账期内命中行大约 2000~8000 行,P99 在 18~45ms 之间,业务暂时能接受,但 filesort 在命中行接近上限时(个别大商户 5 万行)会顶到 400ms+。
【卡点:我卡在两个方案的取舍上,想要量化依据】
方案 A:一个「全都要」的覆盖索引
idx_merchant_create_amt (merchant_id, gmt_create, amount, status, bill_no)
等值 + 范围用前两列消化,剩余列做覆盖。问题在于:
方案 B:拆两个窄索引
idx_merchant_create (merchant_id, gmt_create) -- 过滤
idx_merchant_amount (merchant_id, amount, bill_no) -- 排序 + 部分覆盖
让优化器二选一:命中行少时走 A 索引过滤,命中行多时走 B 索引排序。风险是:
【已尝试与结果】
【期望得到的答案形态】
欢迎贴你们的表规模、命中行分布、EXPLAIN 和压测数据,我这边可以把我手上的三组实测数字完整贴出来对照。