Интернет-магазин: стопор с архитектурой таблицы с товарами (для разных требуются разные поля)

alekciy

Новичок
Я уже поднимал тут такой вопрос, и в своей задачи решил так:
В основной таблице, общие для всех полей значения, и таблица параметров с различными для разных категорий полями,
Как по мне, так не очень удобная система в плане кода. Источник параметров для товара может находится в разных местах внутри базы и это учитывать нужно в коде. Мелочь вроде, а неприятно ибо уходит единообразие выборке параметров.

Пробовал так, на первый взгляд самый очевидный вариант, но сильно притормаживает.
Сам использую отдельную таблицу для товара (понимая под этим аналог "класс", к примеру, рубашка), отдельную для характеристик и третью для связи. Товарные позиции (аналог экземпляра класса, к примеру: рубашка красная, рубашка синяя....) в отдельном таблице. Не сказал бы, что сильно притормаживает. Хотя тут стоит задаваться критериями тормознутости. Характеристик у меня около 10 000, товаров 250 000, на каждый товар в среднем 10 параметров. Получить по id товар и все его характеристики занимает 0,0001 сек. Для интернет магазина такую величину тормозной я бы не назвал.
 

alekciy

Новичок
Кстати замечу, что схема очень удобная в плане гибкости. Любой параметр можно прицепить к любому товару. Для сервисов сравнения очень удобно, ведь бывают разные товара, но с одинаковыми характеристиками. К примеру, диагональ экрана монитора и телевизора или даже бука. Если характеристика "диагональ экрана" прицеплена к товарам "монитор", "телевизор", "ноутбук", то становиться возможно без шаманских плясок сравнить разные типы товаров по схожим параметров, ибо у все у них id параметра одинаков. Конечно при условии, что параметр "диагональ" в таблице параметров есть в одном экземпляре, а не в трех (диагональ монитора, диагональ телевизора, диагональ ноутбука). В итоге получаем достаточно гибкую схеме с более простым коротким и понятным кодом ибо не нужно маяться вопросом "а где у нас храниться вот этот параметр? в строке? столбец? в этой ли таблице вообще?" потому как все параметры хранятся в записях одной таблицы и только там.
 

scorpion-ds

Новичок
Сам использую отдельную таблицу для товара (понимая под этим аналог "класс", к примеру, рубашка), отдельную для характеристик и третью для связи. Товарные позиции (аналог экземпляра класса, к примеру: рубашка красная, рубашка синяя....) в отдельном таблице. Не сказал бы, что сильно притормаживает. Хотя тут стоит задаваться критериями тормознутости. Характеристик у меня около 10 000, товаров 250 000, на каждый товар в среднем 10 параметров. Получить по id товар и все его характеристики занимает 0,0001 сек. Для интернет магазина такую величину тормозной я бы не назвал.
Быстро получилось, у меня на тестовой базе с описанной архитектурой и позиций 50000 случайно сгенерированных, на запрос уходило в районе 0,3-0,5 сек. это без работы PHP кода, потому я и отказался от такого варианта, возможно я что-то не оптимизировал.
 

scorpion-ds

Новичок
Кстати, в моей случае, имелась возможность задавать тип поля такой как мне нужно, а не использовать универсальный тип для хранения параметров, хотя в Вашем случае тоже можно запастись несколькими полями с разными типами. Кстати, а как вы выходили из ситуации, если параметр является справочником? У нас такое часто, к примеру для того же параметра диагональ "19", "22", "23" и т.п.? Это все тоже влияет на скорость работы.
 

alekciy

Новичок
Быстро получилось, у меня на тестовой базе с описанной архитектурой и позиций 50000 случайно сгенерированных, на запрос уходило в районе 0,3-0,5 сек. это без работы PHP кода, потому я и отказался от такого варианта, возможно я что-то не оптимизировал.
Ты уверен, что наставил где нужно индексов? У меня ~250 ms уходило когда я забыл индексов наставить ибо в postresql расстановка внешних ключей автоматически не означает расстановку индексов, в отличие от UNIQUE поля. Сейчас 0,1 ms, но это я еще пока не считаю пределом и оптимальным вариантом. Потому как "товар" можно и нужно хранить в кэше как единую единицу. В идеале будет кэш на shared memory потому как быстрее memcached-а минимум в 4 раза. Но все это на будущее по мере роста.
 

alekciy

Новичок
Кстати, в моей случае, имелась возможность задавать тип поля такой как мне нужно, а не использовать универсальный тип для хранения параметров, хотя в Вашем случае тоже можно запастись несколькими полями с разными типами. Кстати, а как вы выходили из ситуации, если параметр является справочником? У нас такое часто, к примеру для того же параметра диагональ "19", "22", "23" и т.п.? Это все тоже влияет на скорость работы.
В таблице с параметрами есть поле указывающее тип. В таблице со значениями под значения отводятся несколько колонок разного типа: value_int, value_float, value_varchar... и одно поле value тип которого text. Если тип параметра не известен, то пишется в value, т.е. "универсальное" поле, остальное же в null. При известном типе данные пишутся в соответствующую колонку. При этом на value индекса нет, на остальных есть. В целом удобно, особенно когда сначала параметр товара был заведен как, к примеру, целое, в базу записались данные, а потом выяснилось, что оно оказывается дробное. Тогда берем и просто перемещаем из одной колонки в другую.

Параметра справочника быть не может. Потому как справочники должны выделяется в отдельные модули и каталог с ними должен взаимодействовать по API на уровне интерфейсов. Под справочником я понимаю, что-то большее, чем 10-15 записей. Если меньше, то это просто множественные значения параметра, но ни как не справочник. Вообще мне пока такой вариант не нужен, но я бы делал в двух направлениях. В postgresql есть возможность хранить в поле записи массив, соответственно в таблице характеристик заводим поле с именем enum (именно с именем, а не типом, тип у него array) в котором и храним возможные значения. В остальном схема ни как не меняется, если у нас массив с int-ми, то просто пишем в таблицу значений в поле value_int. Если же значений много (к примеру, кода ОКАТО [ибо схема-то применима не только к каталогам товаров, я стараюсь получить нечто большее]) или требуется определенная логика вычисления значения исходя из входных параметров, то получение данных возлагаем на модуль-справочник, в таблице же параметров для данного параметра в поле типов указываем "справочник" и добавляем еще одно поле в котором записаны данные необходимые для вызова справочника.

В общем надеюсь мысль о том, что справочник или перечень возможных значений параметра это не более чем ограничение накладываемое на значения параметра. В таблице значений параметра для конкретного товара у нас все равно уходит одно значение. Если брать приведенных пример, то двух диагоналей у товара быть не может. Поэтому это ни как не влияет на скорость работы, это влияет на код и структуру таблиц, не более.
 

scorpion-ds

Новичок
Верно, справочник это отдельная "система", она же применяется в некоторых других модулях CMS, в таблице данных хранится только выбранное значение, в таблице свойств типа поля, в случае справочника тип "справочник" и сам справочник, который применяется.

За архитектуру я теперь конечно задумаюсь, хотя переделывать уже наверно не буду.
 
Сверху