perf(selfop): cover range reads and stream yearly SKU aggregation

This commit is contained in:
2026-10-13 01:05:52 +08:00
parent a41c271a67
commit 99d206eb00
5 changed files with 54 additions and 7 deletions
@@ -80,7 +80,11 @@ class SelfoperatedAnalyticsSchemaContractTest {
}
assertTrue(run.contains("uk_selfop_inventory_daily (source_account,warehouse_code,inventory_daily_sample_date)"));
assertTrue(run.contains("CONSTRAINT chk_selfop_inventory_daily CHECK"));
assertTrue(ddl.get("ll_selfop_sku_daily_sales").contains("idx_selfop_daily_window (sales_run_id,business_date,customer_code,sku_code)"));
var daily = ddl.get("ll_selfop_sku_daily_sales");
assertTrue(daily.contains("KEY idx_selfop_daily_window_cover (sales_run_id,source_account,warehouse_code,business_date,customer_code,sku_code,outbound_quantity,outbound_order_count,quantity_unit)"));
assertTrue(daily.contains("KEY idx_selfop_daily_sku_cover (sales_run_id,source_account,warehouse_code,customer_code,sku_code,business_date,outbound_quantity,outbound_order_count,quantity_unit)"));
assertFalse(daily.contains("KEY idx_selfop_daily_window ("));
assertTrue(daily.contains("UNIQUE KEY uk_selfop_daily_version (sales_run_id,source_account,customer_code,warehouse_code,sku_code,business_date)"));
assertTrue(ddl.get("ll_selfop_outbound_order").contains("idx_selfop_order_daily (source_account,warehouse_code,sales_eligible,business_date,id)"));
assertTrue(ddl.get("ll_selfop_sync_stage").contains("stage_batch_id,object_type,object_key_hash"));
assertTrue(ddl.get("ll_selfop_sync_stage").contains("observation_sequence IS NOT NULL"));
@@ -42,6 +42,42 @@ public class AnalyticsSqlSemanticTest {
public static LocalDateTime convertZone(LocalDateTime value,String from,String to) {
return value==null?null:value.atOffset(ZoneOffset.of(from)).withOffsetSameInstant(ZoneOffset.of(to)).toLocalDateTime();
}
@Test void skuOrderedCoverHintIsLimitedToExactly366DaySummary() {
for(int days:List.of(1,7,30,365,366,367)) {
var p=request("SUMMARY",D.minusDays(days),D,null,null,utc(D,8),0,20);
String sql=AnalyticsReadSql.page(Map.of("p",p));
String hint="/*+ INDEX(d idx_selfop_daily_sku_cover) */";
assertEquals(days==366,sql.contains(hint),"window="+days);
if(days==366) {
assertTrue(sql.contains("ranged AS (SELECT "+hint+" d.customer_code"));
assertEquals(sql.indexOf(hint),sql.lastIndexOf(hint));
}
assertFalse(AnalyticsReadSql.count(Map.of("p",p)).contains("INDEX("));
}
for(String kind:List.of("HOT","SLOW","INVENTORY")) {
var p=request(kind,D.minusDays(366),D,null,null,utc(D,8),0,20);
assertFalse(AnalyticsReadSql.page(Map.of("p",p)).contains("INDEX("),kind);
}
}
@Test void hinted366DaySummaryPreservesSparseZeroUnknownAndDateBoundaries() throws Exception {
LocalDate from=D.minusDays(365),until=D.plusDays(1);
profile(11,"C","SOLD","VALID_OUTBOUND",utc(from,0),"PCS");
profile(22,"C","ZERO","INVENTORY_OBSERVATION",utc(from,0),"PCS");
profile(22,"C","UNKNOWN","NONE",null,"PCS");
daily(11,"W","C","SOLD",from,"2");daily(11,"W","C","SOLD",D,"3");
daily(11,"W","C","SOLD",from.minusDays(1),"999");daily(11,"W","C","SOLD",until,"999");
daily(33,"W","C","SOLD",from,"999");daily(11,"OTHER","C","SOLD",from,"999");
var p=new AnalyticsSqlRequest("demo","W",null,null,11,22,from,until,D,D.minusDays(30),from,D,
utc(from,0),utc(D,8),true,true,false,true,true,0,20,"SUMMARY");
assertEquals(3,mapper.count(p));var rows=page(p);assertEquals(3,rows.size());
var sold=rows.get(0);assertEquals("SOLD",sold.skuCode());assertDecimal("5",sold.observedQuantity());
assertEquals(2L,sold.skuOrderCount());assertEquals(365,sold.completeDayCount());
assertEquals(1,sold.partialDayCount());assertEquals(0,sold.unknownDayCount());
var zero=rows.get(1);assertEquals("ZERO",zero.skuCode());assertDecimal("0",zero.observedQuantity());
assertEquals(365,zero.completeDayCount());assertEquals(1,zero.partialDayCount());
var unknown=rows.get(2);assertEquals("UNKNOWN",unknown.skuCode());assertNull(unknown.observedQuantity());
assertEquals(0,unknown.completeDayCount());assertEquals(0,unknown.partialDayCount());assertEquals(366,unknown.unknownDayCount());
}
@Test void sqlReturnsTwoCompleteDaysAndTodayPartialObservedFive() throws Exception {
profile(11,"C","SKU","VALID_OUTBOUND",utc(D.minusDays(40),0),"PCS");
profile(22,"C","SKU","INVENTORY_OBSERVATION",utc(D.minusDays(35),0),"PCS");