= Преглед: v_menu_meal = ||= Својство ||= Вредност || || Шема || `kbnteam` || || Категорија || Мени и каталог || || Поврзани индекси || [wiki:MenuMealIndex Индекси за мени и каталог] || == Опис == Ги прикажува јадењата со категорија, ресторан, состојки и алергени. Состојките и алергените се прикажуваат како азбучно подредени листи без повторувања. Се прикажуваат и јадењата без наведени состојки или алергени. Еден ред за секое јадење. Состојките и алергените се азбучно подредени, без повторување на називите. == Зависности == ||= Табела / преглед ||= Употреба || || `kbnteam.meal_ingredient` || Врски меѓу јадењата и состојките. || || `kbnteam.ingredient` || Називи на состојките. || || `kbnteam.alergen_ingredient` || Врски меѓу состојките и алергените. || || `kbnteam.alergen` || Називи на алергените. || || `kbnteam.meal` || Јадења, цени и поврзаност со категорија и ресторан. || || `kbnteam.category` || Категории на јадења. || || `kbnteam.restaurant` || Податоци за рестораните. || == Излезни колони == ||= Колона ||= Извор / пресметка ||= Опис || || `meal_id` || `meal.meal_id` || Идентификатор на јадењето. || || `meal_name` || `meal.meal_name` || Назив на јадењето. || || `meal_description` || `meal.meal_description` || Опис на јадењето. || || `meal_price` || `meal.meal_price` || Цена на јадењето. || || `meal_weight` || `meal.meal_weight` || Тежина на јадењето. || || `cat_id` || `category.cat_id` || Идентификатор на категоријата. || || `cat_name` || `category.cat_name` || Назив на категоријата. || || `rest_id` || `restaurant.rest_id` || Идентификатор на ресторанот. || || `rest_name` || `restaurant.rest_name` || Назив на ресторанот. || || `ingredients` || `COALESCE(meal_ingredients.ingredients, '')` || Подредена листа со називи на состојки. || || `allergens` || `COALESCE(meal_allergens.allergens, '')` || Подредена листа со називи на алергени. || == SQL дефиниција == {{{ #!sql CREATE OR REPLACE VIEW kbnteam.v_menu_meal AS WITH meal_ingredients AS ( SELECT mi.meal_id, string_agg(DISTINCT i.ingr_name, ', ' ORDER BY i.ingr_name) AS ingredients FROM kbnteam.meal_ingredient mi JOIN kbnteam.ingredient i ON i.ingr_id = mi.ingr_id GROUP BY mi.meal_id ), meal_allergens AS ( SELECT mi.meal_id, string_agg(DISTINCT a.alergen_name, ', ' ORDER BY a.alergen_name) AS allergens FROM kbnteam.meal_ingredient mi JOIN kbnteam.alergen_ingredient ai ON ai.ingr_id = mi.ingr_id JOIN kbnteam.alergen a ON a.alergen_id = ai.alergen_id GROUP BY mi.meal_id ) SELECT m.meal_id, m.meal_name, m.meal_description, m.meal_price, m.meal_weight, c.cat_id, c.cat_name, r.rest_id, r.rest_name, COALESCE(mi.ingredients, '') AS ingredients, COALESCE(ma.allergens, '') AS allergens FROM kbnteam.meal m JOIN kbnteam.category c ON c.cat_id = m.cat_id JOIN kbnteam.restaurant r ON r.rest_id = m.rest_id LEFT JOIN meal_ingredients mi ON mi.meal_id = m.meal_id LEFT JOIN meal_allergens ma ON ma.meal_id = m.meal_id; }}} == Тестирање на перформанси == „Пред индексирање“ и „по индексирање“ ги означуваат групите наведени како „без индекси“ и „со индекси“ во евиденцијата. Точниот сет присутни индекси во секоја група не е евидентиран; „без индекси“ не потврдува отсуство на индекси од примарни и уникатни клучеви. Наведените времиња се клиентски мерења од DBeaver, а не серверските Planning Time и Execution Time од EXPLAIN ANALYZE. Нема приложени планови, типови на скенирање или податоци за баферите. Вредностите се во милисекунди (ms). === Измерен прашалник === {{{ #!sql SELECT * FROM kbnteam.v_menu_meal WHERE rest_id = 36 AND cat_id = 5; }}} === Резултати пред индексирање === ||= Метрика ||= Измерен резултат || || Клиентско време (ms) || 106 || || Приказ на мерењето || Статистика за 2 наредби: 106 ms извршување, 0 ms преземање, 106 ms вкупно || || Прикажани / преземени редови || Не е утврден од приказот на статистиката || || Planning Time / Execution Time од EXPLAIN || Не се измерени || || План, тип на скенирање и бафери || Не се приложени || === Дополнителни и заеднички индекси === Уникатното ограничување `uq_meal_restaurant_name` веќе го покрива пребарувањето по ресторан. Обратниот редослед на колоните во индексите за состојки и алергени овозможува пристап од јадење кон состојка и од состојка кон алерген. ||= Индекс ||= Табела и колони ||= Намена || || `idx_meal_cat_id_meal_id` || `meal(cat_id, meal_id)` || Пребарување јадења по категорија. || || `idx_meal_ingredient_meal_id_ingr_id` || `meal_ingredient(meal_id, ingr_id)` || Пристап до состојките на јадењето и групирање по meal_id. || || `idx_alergen_ingredient_ingr_id_alergen_id` || `alergen_ingredient(ingr_id, alergen_id)` || Пристап до алергените поврзани со состојката. || {{{ #!sql CREATE INDEX IF NOT EXISTS idx_meal_cat_id_meal_id ON kbnteam.meal (cat_id, meal_id); CREATE INDEX IF NOT EXISTS idx_meal_ingredient_meal_id_ingr_id ON kbnteam.meal_ingredient (meal_id, ingr_id); CREATE INDEX IF NOT EXISTS idx_alergen_ingredient_ingr_id_alergen_id ON kbnteam.alergen_ingredient (ingr_id, alergen_id); }}} === Проверка на индексите === {{{ #!sql SELECT tablename, indexname, indexdef FROM pg_indexes WHERE schemaname = 'kbnteam' AND indexname IN ( 'idx_meal_cat_id_meal_id', 'idx_meal_ingredient_meal_id_ingr_id', 'idx_alergen_ingredient_ingr_id_alergen_id' ) ORDER BY tablename, indexname; }}} === Резултати по индексирање === ||= Метрика ||= Измерен резултат || || Клиентско време (ms) || 44 || || Приказ на мерењето || Време прикажано со резултатот во DBeaver || || Прикажани / преземени редови || 0 || || Planning Time / Execution Time од EXPLAIN || Не се измерени || || План, тип на скенирање и бафери || Не се приложени || === Анализа на резултатите === ||= Метрика ||= Пред ||= По ||= Промена на времето || || Клиентско време (ms) || 106 || 44 || -58,5% || Аритметичката разлика е 62 ms (58,5%) пократко време. Сепак, 106 ms е вкупно време во статистика за 2 наредби, а 44 ms е време од приказот на празен резултат. Ова не е контролирана споредба на изолирани SELECT извршувања. Потребни се повторени мерења со ист начин на мерење и пример што враќа јадења. Промената се пресметува како 100 × (време по - време пред) / време пред. Негативна вредност значи пократко време, а позитивна подолго време. Процентот ја опишува разликата меѓу прикажаните вредности. Ова се поединечни набљудувања. Не се евидентирани контролирани повторувања, исти услови за кеширање и оптоварување или точните дефиниции на присутните индекси. Затоа промената на времето не е доказ дека индексите се единствената причина. Не се приложени мерења за INSERT, UPDATE и DELETE. === Дополнително тестирање - сè уште неизмерено === Следниот прашалник служи за ново мерење на серверскиот план со истиот филтер. Неговите резултати не се пополнети со клиентските времиња наведени погоре. За споредба се задржуваат исти податоци и поставки, се евидентираат присутните индекси, се ажурираат статистиките и се прават повеќе повторувања во двете состојби. Се споредуваат медијаната на времињата и плановите. {{{ #!sql BEGIN READ ONLY; SET LOCAL statement_timeout = '60s'; EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT * FROM kbnteam.v_menu_meal WHERE rest_id = 36 AND cat_id = 5; ROLLBACK; }}} ||= Метрика за дополнителното тестирање ||= Пред ||= По || || Planning Time (ms) || Не е измерено || Не е измерено || || Execution Time (ms) || Не е измерено || Не е измерено || || Тип на скенирање по табела || Не е евидентиран || Не е евидентиран || || Shared Hit Blocks / Shared Read Blocks || Не се измерени || Не се измерени ||