Проектирование базы данных каталога товаров

grave_bird

Создатель
Регистрация
20 Авг 2015
Сообщения
25
Реакции
17
Нужно спроектировать базу данных для каталога товаров. Сейчас есть проблема со связью атрибутов и товаров. Требуется придумать таблицу для хранения атрибутов товаров. У атрибутов могут быть разные типы, такие как Строка, Число и Список. То есть атрибут с типом Строка для каждого товара хранит какой-либо текст, атрибут типа Число хранит для каждого товара число, а атрибут типа Список хранит одно или несколько значений для каждого товара (прим. атрибута Назначение - для ванны, для душевой кабины и т.п.)

Вот какие таблицы я пока смог придумать:

Товар
Для просмотра ссылки Войди или Зарегистрируйся

Атрибут
Для просмотра ссылки Войди или Зарегистрируйся

Атрибуты товаров
Для просмотра ссылки Войди или Зарегистрируйся

Так как у пары Товар-Атрибут может быть несколько значений, я не стал делать primary key, а просто пометил составным индексом product_id и attribute_id.

Надеюсь на советы по улучшению решения.
 

denverkurt

Denve®
Регистрация
23 Дек 2013
Сообщения
749
Реакции
441
вцелом норм
еще надо не забыть добавить индексы для полей участвующих в WHERE, ORDER BY

еще бывает что один товар может относиться к нескольким категориям
тогда стоит убрать из товара category_id и вынести в отдельную таблицу также без primary key - (procuct_id, category_id)
незнаю актуально это в вашем случае или нет

для чего price_min и price_max - я не понял
 

grave_bird

Создатель
Регистрация
20 Авг 2015
Сообщения
25
Реакции
17
denverkurt, спасибо за ответ. Просто не знаю правильно ли создавать таблицу, без первичного ключа.

еще бывает что один товар может относиться к нескольким категориям
В этом случае не будет такого. Например, есть Ванны. В ваннах ничего кроме ванн не будет. А вот категории Акриловые ванны или Угловые ванны - это уже результат выборки товаров из категории Ванны с атрибутом Тип = акриловые.
для чего price_min и price_max - я не понял
Эти поля будут обновляться триггерами при обновлении таблицы с ценами поставщиков.
 

denverkurt

Denve®
Регистрация
23 Дек 2013
Сообщения
749
Реакции
441
Просто не знаю правильно ли создавать таблицу, без первичного ключа.
это нормальная практика, когда связь таблиц один ко многим

P.S.
просто при обновлении товара нужно будет сначала удалить все записи
Код:
DELETE FROM `tovar_attribs` WHERE `product_id` = 123
а потом добавлять новые записи:
Код:
INSERT INTO `tovar_attribs` VALUES (123, 1, 'акриловая'), (123, 1, 'угловая')

а сам товар обновляется через UPDATE
 

Black Hat

Постоялец
Регистрация
15 Май 2015
Сообщения
167
Реакции
111
Просто не знаю правильно ли создавать таблицу, без первичного ключа.
Надо просто правильно выбирать первичный ключ. Может открою для вас Америку, но PRIMARY KEY может быть составным.
Код:
PRIMARY KEY(product_id, attribute_id)
А если запросы будут типа
Код:
WHERE product_id = ... AND attribute_id = ...
или
WHERE product_id = ...
или
WHERE product_id BETWEEN()
То он будет еще и как индекс.
И вот кстати, то что вы собираетесь делать - называется EAV.

еще надо не забыть добавить индексы для полей участвующих в WHERE, ORDER BY
Плохой совет. Надо смотреть 1) какие запросы будут, и 2) как вообще работать с индексами (гуглить профилирование, покрывающие индексы, работа индексов), так как слепое штампование индексов ничего не даст (а индексы могут быть и бесполезные), и даже может сделать хуже:
1. на поддержку индексов при DELETE/UPDATE/INSERT расходуются ресурсы
2. при построении плана запроса сервер будет прорабатывать бесполезные варианты с бесполезными индексами
3. индексы откушивают память, и когда она кончается, перестают хорошо работать и "хорошие" индексы, так как они начинают грузиться с диска, а не из памяти

Это так, небольшой ликбез

А вообще автор, в последней версии MySQL появился тип JSON - все можно уместить в одну колонку, и без кучи других связок! И по JSON можно кстати индекс построить по отдельным полям. Крутая штука, советую присмотреться
 

denverkurt

Denve®
Регистрация
23 Дек 2013
Сообщения
749
Реакции
441
в данном случае я думаю все индексы на основные поля себя оправдают
таблица товаров в каталоге - один из самых важных моментов, это не какая-нибудь таблица сессий и т.п., записи в которых будут часто будут часто добавляться\изменяться\удаляться
PRIMARY KEY(product_id, attribute_id)
такой первичный ключ позволит создавать связи один ко многим?
А вообще автор, в последней версии MySQL появился тип JSON - все можно уместить в одну колонку, и без кучи других связок! И по JSON можно кстати индекс построить по отдельным полям. Крутая штука, советую присмотреться
а если нужен будет фильтр по атрибутам сделать в один проход, с этим JSON тоже справится?
 

nejtr0n

Гуру форума
Регистрация
24 Янв 2014
Сообщения
129
Реакции
81
Если используете СУБД отличную от myqsl (oracle,sqlserve,postgres), то можете создать свой собственный тип для значений свойств (что то вроде
Код:
CREATE TYPE sql_variant AS
   (i int4,
    l int4,
    t text,
    m money,
    r int4range,
    p geometry
);
)
 

Black Hat

Постоялец
Регистрация
15 Май 2015
Сообщения
167
Реакции
111
такой первичный ключ позволит создавать связи один ко многим?
не надо абсолютизировать, я как пример привел, автор, судя по задаваемым вопросам, вообще не в курсе про составные ключи. если неск значений у свойств - тогда в примари кей prod, attr, value - будет покрывающий индекс - вообще супер
если нужен будет фильтр по атрибутам сделать в один проход, с этим JSON тоже справится?
один проход - это один запрос? вполне
Ну и кстати, советую посмотреть видео с Highload 2005 Андрея Аксенова "Выбираем поиск умом головы", там он говорит о том, что субд хорошо заточены под транзакции, а поиск лучше делать на спец движках (его любимом Сфинксе). Почему - в видео :)
 

grave_bird

Создатель
Регистрация
20 Авг 2015
Сообщения
25
Реакции
17
ключ позволит создавать связи один ко многим
Тут, скорее, много-ко-многим
PRIMARY KEY(product_id, attribute_id)
Тогда я не смогу создавать несколько разных значений одного атрибута для товара.
тогда в примари кей prod, attr, value - будет покрывающий индекс - вообще супер
Вот так я и хотел сделать изначально, но вылазит ошибка - #1071 - Specified key was too long; max key length is 767 bytes. Поэтому, я выбрал другое решение. Я добавил колонку search_hash, которая содержит хэш первого, второго и третьего столбца и обозначил его primary key. Хотя, придётся как-то присматривать за коллизиями, или что-то в таком духе. Но, в теории, работать должно. А возможно и не придётся приглядывать за коллизиями.
За видео отдельное спасибо :)
 
Последнее редактирование:

denverkurt

Denve®
Регистрация
23 Дек 2013
Сообщения
749
Реакции
441
Ну и кстати, советую посмотреть видео с Highload 2005 Андрея Аксенова "Выбираем поиск умом головы", там он говорит о том, что субд хорошо заточены под транзакции, а поиск лучше делать на спец движках (его любимом Сфинксе). Почему - в видео :)
вы про это видео?
о том как выпаривать воду из г**на и прочий геморрой?

для 99% пхп кодеров это нафиг не надо, им бы просто запустить небольшой проект с 10-50 тысяч товаров максимум и чтобы работало на любом хостинге
 
Сверху