perf: avoid promotion sku map scans

This commit is contained in:
WuYongJie 2026-09-01 13:23:31 +08:00
parent 344b8331f4
commit b1bfbe2400
2 changed files with 10 additions and 32 deletions

View File

@ -99,36 +99,19 @@ class OrderDataMirrorRepository
}
if (($filters['sku_id'] ?? '') !== '') {
$needle = $this->contains((string) $filters['sku_id']);
$query->where(function (Builder $items) use ($needle): void {
$items->whereRaw("c.item_id LIKE ? ESCAPE '!'", [$needle])
->orWhereExists(function (Builder $mapping) use ($needle): void {
$mapping->selectRaw('1')->from('ops_jst_sku_map as filter_map')
->whereColumn('filter_map.shop_i_id', 'c.item_id')
->where(function (Builder $codes) use ($needle): void {
$codes->whereRaw("filter_map.sku_id LIKE ? ESCAPE '!'", [$needle])
->orWhereRaw("filter_map.i_id LIKE ? ESCAPE '!'", [$needle])
->orWhereRaw("filter_map.shop_sku_id LIKE ? ESCAPE '!'", [$needle]);
});
});
});
// jst_skumap 的业务编码是 LONGTEXT 且有两千多万行,不能在页面
// 请求中做模糊关联;推广账单自身的 item_id 是稳定可筛选字段。
$query->whereRaw("c.item_id LIKE ? ESCAPE '!'", [$needle]);
}
$rows = $query->select(['c.shop_name', 'c.item_id as shop_style_code', 'c.push_fee as promotion_fee'])
->orderByDesc('c.push_fee')->orderBy('c.shop_name')->orderBy('c.item_id')
->offset((max($page, 1) - 1) * $limit)->limit($limit + 1)
->get()->map(static fn (object $row): array => (array) $row)->all();
$itemIds = array_values(array_unique(array_filter(array_column($rows, 'shop_style_code'))));
$mappings = $itemIds === [] ? collect() : $this->connection->table('ops_jst_sku_map as m')
->leftJoin('ops_jst_shop_info as shop', 'shop.shop_id', '=', 'm.shop_id')
->whereIn('m.shop_i_id', $itemIds)->orderByDesc('m.modified')
->get(['m.shop_i_id', 'm.sku_id', 'm.i_id', 'm.shop_sku_id', 'm.properties_value', 'shop.shop_name'])
->groupBy('shop_i_id');
foreach ($rows as &$row) {
$candidates = $mappings->get($row['shop_style_code'], collect());
$mapping = $candidates->firstWhere('shop_name', $row['shop_name']) ?? $candidates->first();
$row['product_code'] = $mapping->sku_id ?? null;
$row['style_code'] = $mapping->i_id ?? null;
$row['shop_product_code'] = $mapping->shop_sku_id ?? null;
$row['online_color_spec'] = $mapping->properties_value ?? null;
$row['product_code'] = null;
$row['style_code'] = null;
$row['shop_product_code'] = $row['shop_style_code'];
$row['online_color_spec'] = null;
$row['promotion_fee'] = round((float) $row['promotion_fee'], 2);
}
unset($row);

View File

@ -79,19 +79,13 @@ class OrderDataMirrorRepositoryTest extends TestCase
$this->assertNull($row['account_8001201']);
}
public function test_promotion_expenses_read_the_shared_statistics_and_sku_mapping(): void
public function test_promotion_expenses_use_the_bill_item_without_scanning_the_large_sku_map(): void
{
$db = DB::connection('business_mirror');
$db->table('ops_item_sales_cost_ratio')->insert([
'stat_date' => '2026-08-09 00:00:00', 'shop_name' => '京东店铺',
'item_id' => 'ITEM-1', 'push_fee' => 9.05,
]);
$db->table('ops_jst_shop_info')->insert(['shop_id' => 8, 'shop_name' => '京东店铺']);
$db->table('ops_jst_sku_map')->insert([
'shop_i_id' => 'ITEM-1', 'shop_id' => 8, 'sku_id' => 'SKU-1',
'i_id' => 'STYLE-1', 'shop_sku_id' => 'SHOP-SKU-1',
'properties_value' => '黑色', 'modified' => '2026-08-09 10:00:00',
]);
$mirror = Mockery::mock(GenericBusinessMirrorRepository::class);
$mirror->shouldReceive('connection')->andReturn($db);
$repository = new OrderDataMirrorRepository(
@ -103,7 +97,8 @@ class OrderDataMirrorRepositoryTest extends TestCase
], 1, 25);
$this->assertSame('2026-08-09', $result['date']);
$this->assertSame('SKU-1', $result['rows'][0]['product_code']);
$this->assertNull($result['rows'][0]['product_code']);
$this->assertSame('ITEM-1', $result['rows'][0]['shop_product_code']);
$this->assertSame(9.05, $result['rows'][0]['promotion_fee']);
}