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

Тема в разделе "Базы данных", создана пользователем grave_bird, 27 ноя 2016.

Модераторы: latteo
  1. grave_bird

    grave_bird Создатель

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

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

    Товар
    [​IMG]

    Атрибут
    [​IMG]

    Атрибуты товаров
    [​IMG]

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

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

    denverkurt Denve®

    Регистр.:
    23 дек 2013
    Сообщения:
    723
    Симпатии:
    396
    вцелом норм
    еще надо не забыть добавить индексы для полей участвующих в WHERE, ORDER BY

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

    для чего price_min и price_max - я не понял
     
    grave_bird нравится это.
  3. grave_bird

    grave_bird Создатель

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

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

    denverkurt Denve®

    Регистр.:
    23 дек 2013
    Сообщения:
    723
    Симпатии:
    396
    это нормальная практика, когда связь таблиц один ко многим

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

    Black Hat

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

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

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

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

    denverkurt Denve®

    Регистр.:
    23 дек 2013
    Сообщения:
    723
    Симпатии:
    396
    в данном случае я думаю все индексы на основные поля себя оправдают
    таблица товаров в каталоге - один из самых важных моментов, это не какая-нибудь таблица сессий и т.п., записи в которых будут часто будут часто добавляться\изменяться\удаляться
    такой первичный ключ позволит создавать связи один ко многим?
    а если нужен будет фильтр по атрибутам сделать в один проход, с этим JSON тоже справится?
     
    grave_bird нравится это.
  7. nejtr0n

    nejtr0n Постоялец

    Регистр.:
    24 янв 2014
    Сообщения:
    127
    Симпатии:
    72
    Если используете СУБД отличную от myqsl (oracle,sqlserve,postgres), то можете создать свой собственный тип для значений свойств (что то вроде
    Код:
    CREATE TYPE sql_variant AS
       (i int4,
        l int4,
        t text,
        m money,
        r int4range,
        p geometry
    );
    )
     
    Yulo и grave_bird нравится это.
  8. Black Hat

    Black Hat

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

    grave_bird Создатель

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

    denverkurt Denve®

    Регистр.:
    23 дек 2013
    Сообщения:
    723
    Симпатии:
    396
    вы про это видео?
    о том как выпаривать воду из г**на и прочий геморрой?

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