add daily paid view
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Hyperf\DbConnection\Db;
|
||||
use Hyperf\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// PG 原生物化视图:按付款日聚合(仅已付订单)。
|
||||
// 不带 WITH (timescaledb.continuous):TimescaleDB 连续聚合的 time_bucket
|
||||
// 必须基于 hypertable 主时间列(created_date),无法对 paid_date 分桶。
|
||||
// WITH NO DATA:避免 migrate 时长时间锁;首次填充由 P22.3 回填命令执行。
|
||||
Db::statement(<<<'SQL'
|
||||
CREATE MATERIALIZED VIEW orders_daily_by_paid AS
|
||||
SELECT
|
||||
paid_date::date AS day,
|
||||
company_id,
|
||||
platform_id,
|
||||
store_id,
|
||||
COUNT(*) AS paid_orders,
|
||||
SUM(total_amount) AS sum_total_amount,
|
||||
SUM(total_paid) AS sum_total_paid,
|
||||
SUM(total_received) AS sum_total_received,
|
||||
AVG(total_paid) AS avg_paid_amount,
|
||||
SUM(freight_fee) AS sum_freight_fee,
|
||||
SUM(tax_fee) AS sum_tax_fee,
|
||||
SUM(commission_fee) AS sum_commission_fee,
|
||||
SUM(discount_fee) AS sum_discount_fee
|
||||
FROM orders
|
||||
WHERE paid_date IS NOT NULL
|
||||
GROUP BY day, company_id, platform_id, store_id
|
||||
WITH NO DATA;
|
||||
SQL);
|
||||
|
||||
// UNIQUE 索引:REFRESH MATERIALIZED VIEW CONCURRENTLY 的前置条件,缺失会直接报错。
|
||||
Db::statement('CREATE UNIQUE INDEX idx_orders_daily_by_paid_unique ON orders_daily_by_paid (day, company_id, platform_id, store_id)');
|
||||
|
||||
// 5 复合索引:覆盖"最近 N 日按 X 维度"与"指定 X 全历史时间序列"两类高频查询。
|
||||
Db::statement('CREATE INDEX idx_orders_daily_by_paid_day_company ON orders_daily_by_paid (day DESC, company_id)');
|
||||
Db::statement('CREATE INDEX idx_orders_daily_by_paid_day_platform ON orders_daily_by_paid (day DESC, platform_id)');
|
||||
Db::statement('CREATE INDEX idx_orders_daily_by_paid_day_store ON orders_daily_by_paid (day DESC, store_id)');
|
||||
Db::statement('CREATE INDEX idx_orders_daily_by_paid_company_day ON orders_daily_by_paid (company_id, day DESC)');
|
||||
Db::statement('CREATE INDEX idx_orders_daily_by_paid_store_day ON orders_daily_by_paid (store_id, day DESC)');
|
||||
|
||||
// by_created 连续聚合自动刷新策略:每小时刷新近 3 天水位线,1 小时写入缓冲避免与热数据冲突。
|
||||
// 3 天前的修改由 Stage 23 aggregate_refresh_queue 兜底。
|
||||
Db::statement(<<<'SQL'
|
||||
SELECT add_continuous_aggregate_policy(
|
||||
'orders_daily_by_created',
|
||||
start_offset => INTERVAL '3 days',
|
||||
end_offset => INTERVAL '1 hour',
|
||||
schedule_interval => INTERVAL '1 hour'
|
||||
);
|
||||
SQL);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// 先 remove policy,再 drop 视图 CASCADE。
|
||||
// if_exists => true 处理 by_created 视图已被 P22.1 down CASCADE 间接带走的情况。
|
||||
Db::statement("SELECT remove_continuous_aggregate_policy('orders_daily_by_created', if_exists => true)");
|
||||
|
||||
// CASCADE 一并 drop UNIQUE 索引和 5 复合索引。
|
||||
Db::statement('DROP MATERIALIZED VIEW IF EXISTS orders_daily_by_paid CASCADE');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user