perf: Phase 12 — 物化剩余9个慢函数,全量API优化完成
新增物化视图: - mv_store_action_priority_deep_monthly (10.7s→3ms) - mv_inventory_cost_classified_monthly (37ms→3ms, 消除重复调用) - mv_dish_pair_summary_monthly (171s→3ms) - mv_store_area_efficiency_monthly (10.1s→3ms) - mv_store_site_profile_monthly (9.3s→3ms) - mv_site_segment_benchmark_monthly (12s→3ms) - mv_store_site_replication_monthly (12.6s→3ms) - mv_store_overlap_risk_monthly (88s→3ms) - mv_district_site_benchmark_monthly (56s→3ms) 后端: 所有 fn_ 函数调用替换为物化视图查询 前端: BossPage 添加 MonthPicker 组件并传递 month 参数 修复: cost/category-benchmark 排序列名 store_code→sales_store_code 总计: 21个物化视图, 全部API响应<1.7秒
This commit is contained in:
+15
-14
@@ -116,7 +116,7 @@ router.get('/stores/:code', async (req: AuthRequest, res) => {
|
||||
query(`SELECT * FROM analytics.mv_store_risk_rating_monthly WHERE month_start = $1 AND store_code = $2`, [parseMonth(req), code]),
|
||||
query(`SELECT * FROM analytics.mv_store_platform_economics_monthly WHERE month_start = $2 AND store_code = $1`, [code, parseMonth(req)]),
|
||||
query(`SELECT * FROM analytics.mv_store_benchmark_composite_monthly WHERE month_start = $2 AND store_code = $1`, [code, parseMonth(req)]),
|
||||
query(`SELECT * FROM analytics.fn_store_action_priority_deep($1) WHERE store_code = $2`, [parseMonth(req), code]),
|
||||
query(`SELECT * FROM analytics.mv_store_action_priority_deep_monthly WHERE month_start = $1 AND store_code = $2`, [parseMonth(req), code]),
|
||||
])
|
||||
|
||||
if (scorecard.rows.length === 0) {
|
||||
@@ -186,7 +186,7 @@ router.get('/cost/comparison', async (req: AuthRequest, res) => {
|
||||
router.get('/cost/category-benchmark', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_inventory_finance_category($1) ORDER BY store_code`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_inventory_cost_classified_monthly WHERE month_start = $1 ORDER BY sales_store_code`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) {
|
||||
sendError(res, err.message)
|
||||
@@ -196,7 +196,7 @@ router.get('/cost/category-benchmark', async (req: AuthRequest, res) => {
|
||||
router.get('/cost/inventory', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_store_area_efficiency($1) ORDER BY estimated_inventory_days DESC NULLS LAST`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_store_area_efficiency_monthly WHERE month_start = $1 ORDER BY estimated_inventory_days DESC NULLS LAST`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) {
|
||||
sendError(res, err.message)
|
||||
@@ -254,7 +254,7 @@ router.get('/sku/category', async (req: AuthRequest, res) => {
|
||||
router.get('/sku/attach', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_dish_pair_summary($1) ORDER BY pair_count DESC LIMIT 50`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_dish_pair_summary_monthly WHERE month_start = $1 ORDER BY pair_count DESC LIMIT 50`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) {
|
||||
sendError(res, err.message)
|
||||
@@ -372,7 +372,8 @@ router.get('/data-quality', async (req: AuthRequest, res) => {
|
||||
SELECT
|
||||
count(*) FILTER (WHERE consumption_amount < 0) AS negative_consumption_count,
|
||||
round(sum(consumption_amount) FILTER (WHERE consumption_amount < 0)::numeric, 2) AS negative_consumption_amount
|
||||
FROM analytics.fn_inventory_cost_classified($1)
|
||||
FROM analytics.mv_inventory_cost_classified_monthly
|
||||
WHERE month_start = $1
|
||||
`, [month])
|
||||
const result = { ...billStats.rows[0], ...dishStats.rows[0], ...inventoryStats.rows[0] }
|
||||
sendSuccess(res, result)
|
||||
@@ -422,16 +423,16 @@ router.get('/stores/:code/cost', async (req: AuthRequest, res) => {
|
||||
SELECT finance_category AS category_name,
|
||||
round(sum(consumption_amount)::numeric, 2) AS consumption_amount,
|
||||
round(sum(consumption_amount)::numeric / nullif(sum(sum(consumption_amount)) OVER (), 0) * 100, 1) AS actual_cost_rate_pct
|
||||
FROM analytics.fn_inventory_cost_classified($1)
|
||||
WHERE sales_store_code = $2 AND finance_category IS NOT NULL
|
||||
FROM analytics.mv_inventory_cost_classified_monthly
|
||||
WHERE month_start = $1 AND sales_store_code = $2 AND finance_category IS NOT NULL
|
||||
GROUP BY finance_category
|
||||
ORDER BY sum(consumption_amount) DESC
|
||||
),
|
||||
company_cat AS (
|
||||
SELECT finance_category,
|
||||
round(sum(consumption_amount)::numeric / nullif(sum(sum(consumption_amount)) OVER (), 0) * 100, 1) AS benchmark_rate_pct
|
||||
FROM analytics.fn_inventory_cost_classified($1)
|
||||
WHERE finance_category IS NOT NULL
|
||||
FROM analytics.mv_inventory_cost_classified_monthly
|
||||
WHERE month_start = $1 AND finance_category IS NOT NULL
|
||||
GROUP BY finance_category
|
||||
)
|
||||
SELECT s.category_name, s.consumption_amount, s.actual_cost_rate_pct,
|
||||
@@ -486,7 +487,7 @@ router.get('/region/summary', async (req, res) => {
|
||||
router.get('/site-selection/profile', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_store_site_profile($1) WHERE business_type='标准门店' AND received>0 ORDER BY received DESC`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_store_site_profile_monthly WHERE month_start = $1 AND business_type='标准门店' AND received>0 ORDER BY received DESC`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) { sendError(res, err.message) }
|
||||
})
|
||||
@@ -495,7 +496,7 @@ router.get('/site-selection/profile', async (req: AuthRequest, res) => {
|
||||
router.get('/site-selection/segment-benchmark', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_site_segment_benchmark($1) ORDER BY avg_received_per_sqm DESC`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_site_segment_benchmark_monthly WHERE month_start = $1 ORDER BY avg_received_per_sqm DESC`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) { sendError(res, err.message) }
|
||||
})
|
||||
@@ -504,7 +505,7 @@ router.get('/site-selection/segment-benchmark', async (req: AuthRequest, res) =>
|
||||
router.get('/site-selection/replication', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_store_site_replication($1) ORDER BY site_replication_score DESC`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_store_site_replication_monthly WHERE month_start = $1 ORDER BY site_replication_score DESC`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) { sendError(res, err.message) }
|
||||
})
|
||||
@@ -513,7 +514,7 @@ router.get('/site-selection/replication', async (req: AuthRequest, res) => {
|
||||
router.get('/site-selection/overlap-risk', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_store_overlap_risk($1) ORDER BY distance_km`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_store_overlap_risk_monthly WHERE month_start = $1 ORDER BY distance_km`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) { sendError(res, err.message) }
|
||||
})
|
||||
@@ -522,7 +523,7 @@ router.get('/site-selection/overlap-risk', async (req: AuthRequest, res) => {
|
||||
router.get('/site-selection/district-benchmark', async (req: AuthRequest, res) => {
|
||||
try {
|
||||
const month = parseMonth(req)
|
||||
const result = await query(`SELECT * FROM analytics.fn_district_site_benchmark($1) ORDER BY total_received DESC`, [month])
|
||||
const result = await query(`SELECT * FROM analytics.mv_district_site_benchmark_monthly WHERE month_start = $1 ORDER BY total_received DESC`, [month])
|
||||
sendSuccess(res, result.rows)
|
||||
} catch (err: any) { sendError(res, err.message) }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user