модуль 4 из 6 · Акт I · ~30 мин · 7 решений

сцена

Утро вторника. На проекторе — четыре страницы требований, которые Лера собрала с фермеров.

Лера (продакт)
Лера (продакт)

Сыроварня «Три луга» хочет указывать выдержку в месяцах и жирность. Пасека Григорьевых — сорт, год сбора и скорость засахаривания. Овощные хозяйства — сезон, калибр, способ хранения. У каждой категории список свой. И главное — фасетный поиск: покупатель вводит «сыр, жирность 45–50%, выдержка от полугода» и видит три товара, а не листает восемьсот карточек.

Гена (открывает схему)
Гена (открывает схему)

Показываю, как это устроено сейчас. Таблица products: в пятницу было двадцать колонок, я добавил под новые требования — стало сорок. aging_months заполнена у сыров, у остальных NULL. sugar_speed — только у мёда. А когда колонок стало неприлично много, завёл product_attributes: entity — attribute — value, всё строками. Расширяется без миграций.

Тимур (SRE)
Тимур (SRE)

Я вчера ради интереса написал Лерин запрос про жирность. Три самоджойна по product_attributes (чтобы сравнить два атрибута, таблицу приходится соединять саму с собой — по разу на атрибут), CAST строки в число — сорок секунд на нашем объёме. И ещё: у моркови в базе живёт атрибут «засохаривание». С опечаткой. Никто не заметил, потому что валидировать строку value нечем.

Гена
Гена

И сразу, пока не началось: не произносите при мне слово «монга». Джойны — не баг, а фича.

Марина (CTO)
Марина (CTO)

Никто пока не произносил. Каталог — сердце «Ярмарки», и он трещит. Иван, к пятнице — решение: в какой модели данных живут карточки товаров. С аргументами, а не «все так делают».

каталог сегодня · дерево в плоских таблицах
3 self-joinproducts40 nullable-колонокproduct_attributeseav · value: stringкаталогфасетный поиск3 self-join + cast → 40 секунд

Вариативное дерево атрибутов, размазанное по сорока колонкам и таблице «всё строками».

← карта