perf(finance): 优化财务仪表盘聚合查询
This commit is contained in:
@@ -403,7 +403,7 @@ func (r *Repository) dailyEstimates(ctx context.Context, query DashboardQuery) (
|
||||
func (r *Repository) dailySettlements(ctx context.Context, query DashboardQuery) ([]dailySettlementRow, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
rows := make([]dailySettlementRow, 0)
|
||||
err := db.Table("rental_orders AS ro").
|
||||
err := db.Table("rental_orders AS ro USE INDEX (idx_rental_orders_dashboard_settled)").
|
||||
Select(`DATE_FORMAT(ro.settled_at, '%Y-%m-%d') AS date,
|
||||
COALESCE(SUM(oc.platform_fee_cent), 0) AS platform_income_amount_cent,
|
||||
COALESCE(SUM(oc.owner_income_amount_cent), 0) AS owner_should_income_amount_cent,
|
||||
@@ -445,7 +445,7 @@ func (r *Repository) dailySettlements(ctx context.Context, query DashboardQuery)
|
||||
COUNT(ro.id) AS settled_order_count`, settlementDiffThresholdCent, refundBizTypes(), []string{"refunding", "failed"}).
|
||||
// 统计口径:只算"正常结账确认"的订单。仲裁结案的结账单终态是 settled
|
||||
// (由 dispute 模块写入),不纳入本指标,此处保持既有口径不变。
|
||||
Joins("JOIN order_checkouts AS oc ON oc.order_id = ro.id AND oc.status = ?", ordermodule.CheckoutStatusAccepted).
|
||||
Joins("JOIN order_checkouts AS oc USE INDEX (idx_order_checkouts_dashboard_accepted) ON oc.order_id = ro.id AND oc.status = ?", ordermodule.CheckoutStatusAccepted).
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeForSettledOrdersSubquery(db, query)).
|
||||
Where("ro.settled_at >= ? AND ro.settled_at <= ?", query.StartDate, query.EndDate).
|
||||
Group("DATE_FORMAT(ro.settled_at, '%Y-%m-%d')").
|
||||
@@ -523,7 +523,7 @@ func operatingExpenseSummaryFromDailyRows(rows []dailyOperatingExpenseRow) Opera
|
||||
func (r *Repository) dailyPayments(ctx context.Context, query DashboardQuery) ([]dailyPaymentRow, error) {
|
||||
rows := make([]dailyPaymentRow, 0)
|
||||
db := r.db.WithContext(ctx)
|
||||
err := db.Table("payment_orders AS po").
|
||||
err := db.Table("payment_orders AS po USE INDEX (idx_payment_orders_dashboard_created)").
|
||||
Select(`DATE_FORMAT(po.created_at, '%Y-%m-%d') AS date,
|
||||
COALESCE(SUM(CASE WHEN po.biz_type IN ? AND po.status = 'paid' THEN po.amount_cent ELSE 0 END), 0) AS total_flow_amount_cent,
|
||||
COALESCE(SUM(CASE WHEN po.biz_type IN ? AND po.status = 'refunded' THEN po.amount_cent ELSE 0 END), 0) AS total_refund_amount_cent,
|
||||
|
||||
@@ -50,11 +50,11 @@ func ownerWalletIncomeForSettledOrdersSubquery(db *gorm.DB, query DashboardQuery
|
||||
// paymentOriginalAmountForRefundsInRangeSubquery 仅为当前区间内的退款单回查原支付金额。
|
||||
// 退款统计原先会对全部历史支付单按 order_id 聚合;数据增长后这部分即使只看一天也会很慢。
|
||||
func paymentOriginalAmountForRefundsInRangeSubquery(db *gorm.DB, query DashboardQuery) *gorm.DB {
|
||||
refundOrders := db.Table("payment_orders AS refund").
|
||||
refundOrders := db.Table("payment_orders AS refund USE INDEX (idx_payment_orders_dashboard_created)").
|
||||
Select("DISTINCT refund.order_id").
|
||||
Where("refund.biz_type IN ? AND refund.status = ?", refundBizTypes(), "refunded").
|
||||
Where("refund.created_at >= ? AND refund.created_at <= ?", query.StartDate, query.EndDate)
|
||||
return db.Table("payment_orders AS paid").
|
||||
return db.Table("payment_orders AS paid USE INDEX (idx_payment_orders_dashboard_order)").
|
||||
Select("paid.order_id, MAX(paid.amount_cent) AS amount_cent").
|
||||
Joins("JOIN (?) AS refund_order ON refund_order.order_id = paid.order_id", refundOrders).
|
||||
Where("paid.biz_type IN ? AND paid.status = ?", payBizTypes(), "paid").
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
-- +goose Up
|
||||
-- 财务仪表盘按时间窗口聚合支付、退款和结算数据。
|
||||
-- 支付索引避免退款统计扫描全部历史状态;结算与结账索引避免日报聚合回表。
|
||||
ALTER TABLE payment_orders
|
||||
ADD KEY idx_payment_orders_dashboard_created (created_at, biz_type, status, order_id, amount_cent),
|
||||
ADD KEY idx_payment_orders_dashboard_order (order_id, biz_type, status, amount_cent);
|
||||
|
||||
ALTER TABLE rental_orders
|
||||
ADD KEY idx_rental_orders_dashboard_settled (
|
||||
settled_at,
|
||||
id,
|
||||
settlement_mode,
|
||||
offline_settlement_status,
|
||||
offline_settlement_amount_cent,
|
||||
refund_status
|
||||
);
|
||||
|
||||
ALTER TABLE order_checkouts
|
||||
ADD KEY idx_order_checkouts_dashboard_accepted (
|
||||
status,
|
||||
order_id,
|
||||
platform_fee_cent,
|
||||
owner_income_amount_cent
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE order_checkouts
|
||||
DROP KEY idx_order_checkouts_dashboard_accepted;
|
||||
|
||||
ALTER TABLE rental_orders
|
||||
DROP KEY idx_rental_orders_dashboard_settled;
|
||||
|
||||
ALTER TABLE payment_orders
|
||||
DROP KEY idx_payment_orders_dashboard_order,
|
||||
DROP KEY idx_payment_orders_dashboard_created;
|
||||
@@ -31,6 +31,15 @@ require_pattern "backend/internal/database/mysql.go" "SetMaxOpenConns" "连接
|
||||
# 当前财务仪表盘的时间范围聚合和索引是高频查询防线。
|
||||
require_pattern "backend/internal/modules/adminfinance/subquery.go" "settled_at >= ? AND scoped_order.settled_at <= ?" "结算聚合时间范围"
|
||||
require_pattern "backend/internal/modules/adminfinance/dashboard.go" "po.created_at >= ? AND po.created_at <= ?" "支付聚合时间范围"
|
||||
require_pattern "backend/internal/modules/adminfinance/dashboard.go" "USE INDEX (idx_payment_orders_dashboard_created)" "支付聚合时间窗口索引"
|
||||
require_pattern "backend/internal/modules/adminfinance/subquery.go" "USE INDEX (idx_payment_orders_dashboard_created)" "退款统计时间窗口索引"
|
||||
require_pattern "backend/internal/modules/adminfinance/subquery.go" "USE INDEX (idx_payment_orders_dashboard_order)" "退款原金额订单索引"
|
||||
require_pattern "backend/migrations/000091_finance_dashboard_query_indexes.sql" "idx_payment_orders_dashboard_created" "财务支付聚合时间索引"
|
||||
require_pattern "backend/migrations/000091_finance_dashboard_query_indexes.sql" "idx_payment_orders_dashboard_order" "财务退款原金额索引"
|
||||
require_pattern "backend/migrations/000091_finance_dashboard_query_indexes.sql" "idx_rental_orders_dashboard_settled" "财务结算日报覆盖索引"
|
||||
require_pattern "backend/migrations/000091_finance_dashboard_query_indexes.sql" "idx_order_checkouts_dashboard_accepted" "财务结账行覆盖索引"
|
||||
require_pattern "backend/internal/modules/adminfinance/dashboard.go" "USE INDEX (idx_rental_orders_dashboard_settled)" "结算日报时间索引"
|
||||
require_pattern "backend/internal/modules/adminfinance/dashboard.go" "USE INDEX (idx_order_checkouts_dashboard_accepted)" "结算日报结账索引"
|
||||
require_pattern "backend/migrations/000060_finance_dashboard_indexes.sql" "idx_admin_pickups_status_completed_at" "财务完成索引"
|
||||
require_pattern "backend/migrations/000060_finance_dashboard_indexes.sql" "idx_admin_pickups_status_cancelled_at" "财务取消索引"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user