Changes between Initial Version and Version 1 of OrdersFullView


Ignore:
Timestamp:
05/10/26 14:28:03 (2 weeks ago)
Author:
185022
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • OrdersFullView

    v1 v1  
     1= Преглед: v_orders_full =
     2
     3||= Датотека ||= `views/02_orders_full_view.sql` ||
     4||= Шема ||= `kbnteam` ||
     5||= Категорија ||= Нарачки и Достави ||
     6||= Поврзани индекси ||= `indexes/v_orders_full_index.sql` ||
     7||= Сложеност ||= Висока — 2 CTE + 12 табели ||
     8
     9== Опис ==
     10Примарен оперативен преглед за нарачки во веб апликацијата. Ги прикажува целосните детали за нарачка: контекст на купувач/компанија, статус на нарачка, контекст на достава и агрегирани листи на нарачани оброци и пијачи. Двете CTE (`order_meals`, `order_drinks`) ги собираат ставките по нарачка во читливи стрингови.
     11
     12'''Важно:''' Овој преглед е еден од најтешките во шемата. Никогаш не го извршувајте со `SELECT *` без WHERE клаузула при бенчмарк тестирање.
     13
     14== Зависности ==
     15||= Табела ||= Тип на употреба ||
     16|| `kbnteam.customer_order` || Главна табела (нарачка) ||
     17|| `kbnteam.order_status` || JOIN — статус на нарачката ||
     18|| `kbnteam.customer` || JOIN — купувач ||
     19|| `kbnteam.api_user` || JOIN (×2) — детали за купувач и возач ||
     20|| `kbnteam.company_order` || JOIN — компаниска нарачка ||
     21|| `kbnteam.company` || JOIN — компанија ||
     22|| `kbnteam.delivery` || LEFT JOIN — достава ||
     23|| `kbnteam.delivery_status` || LEFT JOIN — статус на достава ||
     24|| `kbnteam.driver` || LEFT JOIN — возач ||
     25|| `kbnteam.order_meal` || LEFT JOIN (CTE) — оброци во нарачката ||
     26|| `kbnteam.meal` || JOIN (CTE) — назив на оброк ||
     27|| `kbnteam.order_drink` || LEFT JOIN (CTE) — пијачи во нарачката ||
     28|| `kbnteam.drink` || JOIN (CTE) — назив на пијач ||
     29
     30== Излезни колони ==
     31||= Колона ||= Извор ||= Опис ||
     32|| `order_id` || `customer_order` || Примарен клуч на нарачката ||
     33|| `order_datetime` || `customer_order` || Датум и час на нарачката ||
     34|| `order_total` || `customer_order` || Вкупна цена ||
     35|| `o_status_name` || `order_status` || Статус на нарачката ||
     36|| `customer_user_id` || `customer` || ID на купувачот ||
     37|| `customer_company_id` || `customer` || ID на компанијата на купувачот ||
     38|| `customer_first_name` || `api_user` || Ime на купувачот ||
     39|| `customer_last_name` || `api_user` || Презиме на купувачот ||
     40|| `customer_email` || `api_user` || Е-пошта на купувачот ||
     41|| `comp_order_id` || `company_order` || ID на компаниската нарачка ||
     42|| `order_company_id` || `company_order` || ID на компанијата ||
     43|| `company_name` || `company` || Назив на компанијата ||
     44|| `delivery_id` || `delivery` || ID на доставата (NULL ако нема) ||
     45|| `delivery_date` || `delivery` || Датум на достава ||
     46|| `d_status_name` || `delivery_status` || Статус на достава ||
     47|| `driver_user_id` || `driver` || ID на возачот ||
     48|| `driver_first_name` || `api_user` || Ime на возачот ||
     49|| `driver_last_name` || `api_user` || Презиме на возачот ||
     50|| `driver_phone` || `api_user` || Телефон на возачот ||
     51|| `meals` || CTE `order_meals` || Оброци одвоени со запирка ||
     52|| `drinks` || CTE `order_drinks` || Пијачи одвоени со запирка ||
     53
     54== SQL Дефиниција ==
     55{{{
     56#!sql
     57CREATE OR REPLACE VIEW kbnteam.v_orders_full AS
     58WITH order_meals AS (
     59    SELECT
     60        x.order_id,
     61        string_agg(x.meal_name, ', ' ORDER BY x.meal_name) AS meals
     62    FROM (
     63        SELECT DISTINCT
     64            om.order_id,
     65            m.meal_name
     66        FROM kbnteam.order_meal om
     67        JOIN kbnteam.meal m ON m.meal_id = om.meal_id
     68    ) x
     69    GROUP BY x.order_id
     70),
     71order_drinks AS (
     72    SELECT
     73        x.order_id,
     74        string_agg(x.drink_name, ', ' ORDER BY x.drink_name) AS drinks
     75    FROM (
     76        SELECT DISTINCT
     77            od.order_id,
     78            d.drink_name
     79        FROM kbnteam.order_drink od
     80        JOIN kbnteam.drink d ON d.drink_id = od.drink_id
     81    ) x
     82    GROUP BY x.order_id
     83)
     84SELECT
     85    o.order_id,
     86    o.order_datetime,
     87    o.order_total,
     88    os.o_status_name,
     89    cu.user_id AS customer_user_id,
     90    cu.company_id AS customer_company_id,
     91    au.user_first_name AS customer_first_name,
     92    au.user_last_name AS customer_last_name,
     93    au.user_email AS customer_email,
     94    co.comp_order_id,
     95    co.company_id AS order_company_id,
     96    cmp.company_name,
     97    d.delivery_id,
     98    d.delivery_date,
     99    ds.d_status_name,
     100    drv.user_id AS driver_user_id,
     101    du.user_first_name AS driver_first_name,
     102    du.user_last_name AS driver_last_name,
     103    du.user_phone_no AS driver_phone,
     104    COALESCE(om.meals, '') AS meals,
     105    COALESCE(od.drinks, '') AS drinks
     106FROM kbnteam.customer_order o
     107JOIN kbnteam.order_status os ON os.o_status_id = o.o_status_id
     108JOIN kbnteam.customer cu ON cu.user_id = o.customer_user_id
     109JOIN kbnteam.api_user au ON au.user_id = cu.user_id
     110JOIN kbnteam.company_order co ON co.comp_order_id = o.comp_order_id
     111JOIN kbnteam.company cmp ON cmp.company_id = co.company_id
     112LEFT JOIN kbnteam.delivery d ON d.delivery_id = co.delivery_id
     113LEFT JOIN kbnteam.delivery_status ds ON ds.d_status_id = d.d_status_id
     114LEFT JOIN kbnteam.driver drv ON drv.user_id = d.driver_user_id
     115LEFT JOIN kbnteam.api_user du ON du.user_id = drv.user_id
     116LEFT JOIN order_meals om ON om.order_id = o.order_id
     117LEFT JOIN order_drinks od ON od.order_id = o.order_id;
     118}}}
     119
     120== Тестирање на перформанси ==
     121
     122=== Препорачано тест прашање ===
     123{{{
     124#!sql
     125SET search_path TO kbnteam;
     126SET statement_timeout = '60s';
     127
     128-- Тест 1: последни 30 дена (временски опсег — тестира idx по datetime)
     129EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
     130SELECT * FROM kbnteam.v_orders_full
     131WHERE order_datetime >= CURRENT_DATE - INTERVAL '30 days';
     132
     133-- Тест 2: по купувач (тестира idx по customer_user_id)
     134EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
     135SELECT * FROM kbnteam.v_orders_full
     136WHERE customer_user_id = 1;
     137
     138-- Тест 3: по компаниска нарачка (тестира idx по comp_order_id)
     139EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
     140SELECT * FROM kbnteam.v_orders_full
     141WHERE comp_order_id = 1;
     142}}}
     143
     144=== Резултати пред индексирање ===
     145Извршете ги горните прашања '''пред''' да ја примените датотеката `indexes/v_orders_full_index.sql`.
     146
     147||= Метрика ||= Тест 1 (datetime) ||= Тест 2 (customer) ||= Тест 3 (comp_order) ||
     148|| Planning Time || ___ ms || ___ ms || ___ ms ||
     149|| Execution Time || ___ ms || ___ ms || ___ ms ||
     150|| Rows Returned || ___ || ___ || ___ ||
     151|| customer_order scan || ___ || ___ || ___ ||
     152|| order_meal scan || ___ || ___ || ___ ||
     153|| delivery scan || ___ || ___ || ___ ||
     154
     155{{{
     156-- Излезот од EXPLAIN ANALYZE овде (пред индексирање)
     157}}}
     158
     159=== Применети индекси ===
     160{{{
     161#!sql
     162-- indexes/v_orders_full_index.sql
     163CREATE INDEX IF NOT EXISTS idx_customer_order_comp_order_id
     164ON kbnteam.customer_order (comp_order_id);
     165
     166CREATE INDEX IF NOT EXISTS idx_customer_order_customer_user_id_order_datetime
     167ON kbnteam.customer_order (customer_user_id, order_datetime DESC);
     168
     169CREATE INDEX IF NOT EXISTS idx_delivery_driver_user_id_delivery_date
     170ON kbnteam.delivery (driver_user_id, delivery_date);
     171
     172CREATE INDEX IF NOT EXISTS idx_order_meal_order_id_meal_id
     173ON kbnteam.order_meal (order_id, meal_id);
     174
     175CREATE INDEX IF NOT EXISTS idx_order_drink_order_id_drink_id
     176ON kbnteam.order_drink (order_id, drink_id);
     177}}}
     178
     179=== Резултати по индексирање ===
     180Извршете ги истите прашања '''по''' примена на `indexes/v_orders_full_index.sql`.
     181
     182||= Метрика ||= Тест 1 (datetime) ||= Тест 2 (customer) ||= Тест 3 (comp_order) ||
     183|| Planning Time || ___ ms || ___ ms || ___ ms ||
     184|| Execution Time || ___ ms || ___ ms || ___ ms ||
     185|| Rows Returned || ___ || ___ || ___ ||
     186|| customer_order scan || ___ || ___ || ___ ||
     187|| order_meal scan || ___ || ___ || ___ ||
     188|| delivery scan || ___ || ___ || ___ ||
     189
     190{{{
     191-- Излезот од EXPLAIN ANALYZE овде (по индексирање)
     192}}}
     193
     194=== Анализа на подобрување ===
     195||= Индекс ||= Помага на ||= Очекувана промена ||
     196|| `idx_customer_order_customer_user_id_order_datetime` || Тест 1 и Тест 2 || Seq Scan → Index Scan на `customer_order` ||
     197|| `idx_customer_order_comp_order_id` || Тест 3 и JOIN со `company_order` || Seq Scan → Index Scan на `customer_order` ||
     198|| `idx_order_meal_order_id_meal_id` || CTE `order_meals` || Seq Scan → Index Scan на `order_meal` ||
     199|| `idx_order_drink_order_id_drink_id` || CTE `order_drinks` || Seq Scan → Index Scan на `order_drink` ||
     200|| `idx_delivery_driver_user_id_delivery_date` || LEFT JOIN на `delivery` || Seq Scan → Index Scan на `delivery` ||
     201
     202||= Метрика ||= Пред ||= По ||= Δ Подобрување ||
     203|| Execution Time (Тест 1) || ___ ms || ___ ms || ___ % ||
     204|| Execution Time (Тест 2) || ___ ms || ___ ms || ___ % ||
     205|| Execution Time (Тест 3) || ___ ms || ___ ms || ___ % ||