4.1.0: Оптимизация получения данных текущей недели
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m22s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m22s
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
|||||||
|
-- Migration: Revert optimization of weekly_report_mv
|
||||||
|
-- Date: 2026-01-26
|
||||||
|
--
|
||||||
|
-- This migration reverts:
|
||||||
|
-- 1. Removes created_date column from nodes table
|
||||||
|
-- 2. Drops indexes
|
||||||
|
-- 3. Restores MV to original structure (include current week, use entries.created_date)
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 1: Recreate MV with original structure
|
||||||
|
-- ============================================
|
||||||
|
DROP MATERIALIZED VIEW IF EXISTS weekly_report_mv;
|
||||||
|
|
||||||
|
CREATE MATERIALIZED VIEW weekly_report_mv AS
|
||||||
|
SELECT
|
||||||
|
p.id AS project_id,
|
||||||
|
agg.report_year,
|
||||||
|
agg.report_week,
|
||||||
|
COALESCE(agg.total_score, 0.0000) AS total_score,
|
||||||
|
CASE
|
||||||
|
WHEN wg.max_score IS NULL THEN COALESCE(agg.total_score, 0.0000)
|
||||||
|
ELSE LEAST(COALESCE(agg.total_score, 0.0000), wg.max_score)
|
||||||
|
END AS normalized_total_score
|
||||||
|
FROM
|
||||||
|
projects p
|
||||||
|
LEFT JOIN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
n.project_id,
|
||||||
|
EXTRACT(ISOYEAR FROM e.created_date)::INTEGER AS report_year,
|
||||||
|
EXTRACT(WEEK FROM e.created_date)::INTEGER AS report_week,
|
||||||
|
SUM(n.score) AS total_score
|
||||||
|
FROM
|
||||||
|
nodes n
|
||||||
|
JOIN
|
||||||
|
entries e ON n.entry_id = e.id
|
||||||
|
GROUP BY
|
||||||
|
1, 2, 3
|
||||||
|
) agg
|
||||||
|
ON p.id = agg.project_id
|
||||||
|
LEFT JOIN
|
||||||
|
weekly_goals wg
|
||||||
|
ON wg.project_id = p.id
|
||||||
|
AND wg.goal_year = agg.report_year
|
||||||
|
AND wg.goal_week = agg.report_week
|
||||||
|
WHERE
|
||||||
|
p.deleted = FALSE
|
||||||
|
ORDER BY
|
||||||
|
p.id, agg.report_year, agg.report_week
|
||||||
|
WITH DATA;
|
||||||
|
|
||||||
|
CREATE INDEX idx_weekly_report_mv_project_year_week
|
||||||
|
ON weekly_report_mv(project_id, report_year, report_week);
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 2: Drop indexes
|
||||||
|
-- ============================================
|
||||||
|
DROP INDEX IF EXISTS idx_nodes_project_user_created_date;
|
||||||
|
DROP INDEX IF EXISTS idx_nodes_created_date_user;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 3: Remove created_date column from nodes
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE nodes
|
||||||
|
DROP COLUMN IF EXISTS created_date;
|
||||||
|
|
||||||
|
COMMENT ON MATERIALIZED VIEW weekly_report_mv IS 'Materialized view aggregating weekly scores by project using ISOYEAR for correct week calculations at year boundaries. Includes all projects via LEFT JOIN. Adds normalized_total_score using weekly_goals.max_score snapshot.';
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
-- Migration: Optimize weekly_report_mv by denormalizing created_date into nodes and excluding current week from MV
|
||||||
|
-- Date: 2026-01-26
|
||||||
|
--
|
||||||
|
-- This migration:
|
||||||
|
-- 1. Adds created_date column to nodes table (denormalization to avoid JOIN with entries)
|
||||||
|
-- 2. Populates existing data from entries
|
||||||
|
-- 3. Creates indexes for optimized queries
|
||||||
|
-- 4. Updates MV to exclude current week and use nodes.created_date instead of entries.created_date
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 1: Add created_date column to nodes
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE nodes
|
||||||
|
ADD COLUMN created_date TIMESTAMP WITH TIME ZONE;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 2: Populate existing data from entries
|
||||||
|
-- ============================================
|
||||||
|
UPDATE nodes n
|
||||||
|
SET created_date = e.created_date
|
||||||
|
FROM entries e
|
||||||
|
WHERE n.entry_id = e.id;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 3: Set NOT NULL constraint
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE nodes
|
||||||
|
ALTER COLUMN created_date SET NOT NULL;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 4: Create indexes for optimized queries
|
||||||
|
-- ============================================
|
||||||
|
-- Index for filtering by date and user (for current week queries)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_nodes_created_date_user
|
||||||
|
ON nodes(created_date, user_id);
|
||||||
|
|
||||||
|
-- Index for queries with grouping by project (for current week queries)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_nodes_project_user_created_date
|
||||||
|
ON nodes(project_id, user_id, created_date);
|
||||||
|
|
||||||
|
COMMENT ON INDEX idx_nodes_created_date_user IS 'Index for filtering nodes by created_date and user_id - optimized for current week queries';
|
||||||
|
COMMENT ON INDEX idx_nodes_project_user_created_date IS 'Index for grouping nodes by project, user and created_date - optimized for current week aggregation queries';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- Step 5: Recreate MV to exclude current week and use nodes.created_date
|
||||||
|
-- ============================================
|
||||||
|
DROP MATERIALIZED VIEW IF EXISTS weekly_report_mv;
|
||||||
|
|
||||||
|
CREATE MATERIALIZED VIEW weekly_report_mv AS
|
||||||
|
SELECT
|
||||||
|
p.id AS project_id,
|
||||||
|
agg.report_year,
|
||||||
|
agg.report_week,
|
||||||
|
COALESCE(agg.total_score, 0.0000) AS total_score,
|
||||||
|
CASE
|
||||||
|
WHEN wg.max_score IS NULL THEN COALESCE(agg.total_score, 0.0000)
|
||||||
|
ELSE LEAST(COALESCE(agg.total_score, 0.0000), wg.max_score)
|
||||||
|
END AS normalized_total_score
|
||||||
|
FROM
|
||||||
|
projects p
|
||||||
|
LEFT JOIN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
n.project_id,
|
||||||
|
EXTRACT(ISOYEAR FROM n.created_date)::INTEGER AS report_year,
|
||||||
|
EXTRACT(WEEK FROM n.created_date)::INTEGER AS report_week,
|
||||||
|
SUM(n.score) AS total_score
|
||||||
|
FROM
|
||||||
|
nodes n
|
||||||
|
WHERE
|
||||||
|
-- Exclude current week: only include data from previous weeks
|
||||||
|
(EXTRACT(ISOYEAR FROM n.created_date)::INTEGER < EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER)
|
||||||
|
OR (EXTRACT(ISOYEAR FROM n.created_date)::INTEGER = EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER
|
||||||
|
AND EXTRACT(WEEK FROM n.created_date)::INTEGER < EXTRACT(WEEK FROM CURRENT_DATE)::INTEGER)
|
||||||
|
GROUP BY
|
||||||
|
1, 2, 3
|
||||||
|
) agg
|
||||||
|
ON p.id = agg.project_id
|
||||||
|
LEFT JOIN
|
||||||
|
weekly_goals wg
|
||||||
|
ON wg.project_id = p.id
|
||||||
|
AND wg.goal_year = agg.report_year
|
||||||
|
AND wg.goal_week = agg.report_week
|
||||||
|
WHERE
|
||||||
|
p.deleted = FALSE
|
||||||
|
ORDER BY
|
||||||
|
p.id, agg.report_year, agg.report_week
|
||||||
|
WITH DATA;
|
||||||
|
|
||||||
|
-- Recreate index on MV
|
||||||
|
CREATE INDEX idx_weekly_report_mv_project_year_week
|
||||||
|
ON weekly_report_mv(project_id, report_year, report_week);
|
||||||
|
|
||||||
|
COMMENT ON MATERIALIZED VIEW weekly_report_mv IS 'Materialized view aggregating weekly scores by project using ISOYEAR for correct week calculations at year boundaries. Includes all projects via LEFT JOIN. Adds normalized_total_score using weekly_goals.max_score snapshot. Contains only historical data (excludes current week). Uses nodes.created_date (denormalized) instead of entries.created_date.';
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "play-life-web",
|
"name": "play-life-web",
|
||||||
"version": "4.0.6",
|
"version": "4.1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
Reference in New Issue
Block a user