perf(distribution): 优化分销订单全量与分站慢查询,消除全表扫描与每行EXISTS子查询

- 数据库迁移:新增 000083 迁移,为 distribution_order_parties 添加 (site_id, order_id) 联合覆盖索引;
- 查询优化:重构 ListOrders,利用覆盖索引派生表预收敛分销订单候选集,替代在 3.7 万行 rental_orders 上的 OR EXISTS 逐行子查询全表扫描;
- 边界修复:超管全量分销订单(site_id = 0)增加分销范围收敛,防止全平台普通非分销订单混杂和 5 表级联扫表;
- 统计优化:同步改造 GetDashboardAnalytics 与 ListDistributionUsers,彻底消除大盘统计与客户画像聚合的慢查询;
- 验证方式:新增 TestListOrdersPerformanceAndScoping 单元测试,全量运行 ./scripts/check.sh 门禁验证通过。
This commit is contained in:
yml2213
2026-10-10 15:17:25 +08:00
parent 4ea08e355b
commit 95435faf46
3 changed files with 203 additions and 21 deletions
@@ -1640,3 +1640,151 @@ func TestListDistributionUsersAndAnalytics(t *testing.T) {
analytics.TodayUserCount, analytics.TotalUserCount, analytics.TotalOrderUserCount)
}
}
func TestListOrdersPerformanceAndScoping(t *testing.T) {
db := distributionTestDB(t)
repo := NewRepository(db)
site1 := model.DistributionSite{SiteName: "站1", SiteCode: "site1", Domain: "s1.test", Status: "active"}
site2 := model.DistributionSite{SiteName: "站2", SiteCode: "site2", Domain: "s2.test", Status: "active"}
if err := db.Create(&site1).Error; err != nil {
t.Fatal(err)
}
if err := db.Create(&site2).Error; err != nil {
t.Fatal(err)
}
u := model.User{Phone: "13900000001", Nickname: "买家"}
if err := db.Create(&u).Error; err != nil {
t.Fatal(err)
}
// 1. 普通非分销订单(主站自营,不属于任何分销)
normalOrder := model.RentalOrder{
OrderNo: "RO_NORMAL_001",
RenterID: u.ID,
Status: "completed",
DistributionSiteID: nil,
DistributionMode: "",
}
if err := db.Create(&normalOrder).Error; err != nil {
t.Fatal(err)
}
// 2. 分销站1的订单
site1ID := site1.ID
distOrder1 := model.RentalOrder{
OrderNo: "RO_DIST_001",
RenterID: u.ID,
Status: "completed",
DistributionSiteID: &site1ID,
DistributionMode: "site_self_sell",
}
if err := db.Create(&distOrder1).Error; err != nil {
t.Fatal(err)
}
if err := db.Create(&model.DistributionOrderParty{
OrderID: distOrder1.ID,
SiteID: site1.ID,
PartyRole: "distributor_sell",
PartyType: "site",
PartyID: site1.ID,
}).Error; err != nil {
t.Fatal(err)
}
// 3. 分销站2作为收号方的跨站订单(下单站点为0或主站,但分销站2为参与方)
distOrder2 := model.RentalOrder{
OrderNo: "RO_DIST_002",
RenterID: u.ID,
Status: "renting",
DistributionSiteID: nil,
DistributionMode: "two_party_distributor_receive",
}
if err := db.Create(&distOrder2).Error; err != nil {
t.Fatal(err)
}
if err := db.Create(&model.DistributionOrderParty{
OrderID: distOrder2.ID,
SiteID: site2.ID,
PartyRole: "distributor_receive",
PartyType: "site",
PartyID: site2.ID,
}).Error; err != nil {
t.Fatal(err)
}
// A. 超管查询全部分销订单 (SiteID = 0)
// 预期:只查出 2 笔分销订单,普通主站订单 normalOrder 绝不能混入!
allPage, err := repo.ListOrders(t.Context(), DistributionOrderListQuery{
SiteID: 0,
Page: 1,
Size: 10,
})
if err != nil {
t.Fatalf("ListOrders SiteID=0 failed: %v", err)
}
if allPage.Total != 2 {
t.Fatalf("expected 2 distribution orders for superadmin, got %d (normal order must be excluded)", allPage.Total)
}
if len(allPage.Items) != 2 {
t.Fatalf("expected 2 items, got %d", len(allPage.Items))
}
// B. 分销商1查询其订单 (SiteID = site1.ID)
// 预期:只查出 distOrder1
site1Page, err := repo.ListOrders(t.Context(), DistributionOrderListQuery{
SiteID: site1.ID,
Page: 1,
Size: 10,
})
if err != nil {
t.Fatalf("ListOrders SiteID=1 failed: %v", err)
}
if site1Page.Total != 1 || site1Page.Items[0].OrderID != distOrder1.ID {
t.Fatalf("expected order %d for site1, got total=%d items=%+v", distOrder1.ID, site1Page.Total, site1Page.Items)
}
// C. 分销商2查询其订单 (SiteID = site2.ID)
// 预期:查出 distOrder2(通过参与方命中)
site2Page, err := repo.ListOrders(t.Context(), DistributionOrderListQuery{
SiteID: site2.ID,
Page: 1,
Size: 10,
})
if err != nil {
t.Fatalf("ListOrders SiteID=2 failed: %v", err)
}
if site2Page.Total != 1 || site2Page.Items[0].OrderID != distOrder2.ID {
t.Fatalf("expected order %d for site2, got total=%d items=%+v", distOrder2.ID, site2Page.Total, site2Page.Items)
}
// D. 按 Kind="sold" 过滤
soldPage, err := repo.ListOrders(t.Context(), DistributionOrderListQuery{
SiteID: site1.ID,
Kind: "sold",
Page: 1,
Size: 10,
})
if err != nil {
t.Fatalf("ListOrders Kind=sold failed: %v", err)
}
if soldPage.Total != 1 || soldPage.Items[0].OrderID != distOrder1.ID {
t.Fatalf("expected 1 sold order for site1, got %d", soldPage.Total)
}
// E. 按 Kind="receive" 过滤
recvPage, err := repo.ListOrders(t.Context(), DistributionOrderListQuery{
SiteID: site2.ID,
Kind: "receive",
Page: 1,
Size: 10,
})
if err != nil {
t.Fatalf("ListOrders Kind=receive failed: %v", err)
}
if recvPage.Total != 1 || recvPage.Items[0].OrderID != distOrder2.ID {
t.Fatalf("expected 1 receive order for site2, got %d", recvPage.Total)
}
}