За последние 24 часа нас посетили 17760 программистов и 1643 робота. Сейчас ищут 1672 программиста ...

Как проектировать БД для инет-магазина

Тема в разделе "MySQL", создана пользователем Koc, 12 сен 2008.

  1. Нет серебрянных плоскогубцев.

    3NF всего лишь профилактическое лечение геммороя.

     
  2. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Вариант с горизонтальным растяжением таблицы при добавлении новой характеристики (у тебя это "опции") товара даже не рассматривается? ;)
     
  3. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Это я уже прочел)
    Не очень понимаю различие между 2 и 3 формой... уже 2 статью читаю..
    UPD: понял)
     
  4. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Dagdamor
    Неа, не рассматривается.
    У меня-то товаров не много в базе, порядка 100-300 будет, поэтому можно и рассмотреть. Но мне такое решение не нравится в корне:
    1. Не красиво
    2. Не удобно (ковырять лишние параметры)
    3. Если представить, что у меня в базе 50 типов товаров и каждый обладает десятком уникальных свойств. Не очень хочется видеть таблицу с продукцией, где 500 атрибутов, которые используются через сотню-другую :lol:
     
  5. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Kreker
    Что есть красиво, а что некрасиво? Хранить данные разного типа в одном поле - красиво?
    Какие именно?
    Это магазин или выставка сферических коней в вакууме? На практике количество атрибутов не превышает 20-30, причем независимо от общего количества товаров в магазине. По одной простой причине - вести такой магазин иначе становится невозможно.
     
  6. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Dagdamor
    У меня в админке при выборе типа товара будут подгружаться его возможные свойства, чтобы при добавлении телевизора не было возможности выбрать тип HEPA-фильтра :) А возможно ли определить, какие свойства допустимы у категории товара, если заведомо неизвестно, все ли поля заполнены у первого попавшегося товара категории?

    А разве красиво когда у товара десяток лишних нуль-полей?

    Незнание точного количества полей в таблице - не есть хорошо, все конструкция получается плавающей. Сайт работает на заранее неизвестных данных.

    При добавлении нового свойства, приходится добавлять новое поле, а значит, перелопачивать всю таблицу.

    При добавлении нового свойства необходимо и задуматься о его имени. Адмонимус - вещь неожиданная.

    Лично мое мнение, что горизонтальное расширение таблицы принесет слишком много гемора. Не хочу, не буду. Занимался этим спустя полгода сайтописания, но быстро перестал.
     
  7. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Kreker
    Если при создании нового товара есть возможность определить, какой у него список характеристик, как получается, что при редактировании товара ты этого узнать уже не можешь? :)

    А разве красиво, когда для выбора половины свойств товара нужен один запрос, а для выбора второй половины - другой?

    Незнание точного количества товаров в каталоге - не есть хорошо, все конструкция получается плавающей. Сайт работает на заранее неизвестных данных.

    Разумеется. Однако чего вы все так трясетесь при мысли об одном ALTER TABLE в административной зоне - не понимаю. Ну допустим, миллион товаров в таблице. Ну допустим, запрос будет работать минуту, приостановив работу магазина на эту самую минуту. Это критично? Ты гораздо больше потеряешь на лишних запросах к таблицам-связкам, а ведь эти лишние запросы будут выполняться не раз в неделю, а сотни раз в секунду.
    А если товаров немного - тысячи или десятки тысяч - таблица перестраивается за доли секунды, максимум за несколько секунд на самом старом и унылом железе. Не бойтесь вы структуру таблицы менять, как дети, право слово.

    Да, это серьезная проблема :D

    Как раз возня с дополнительными таблицами принесет намного больше гемора. Сравни типичные запросы - например, показать страницу каталога. В случае одной таблицы и запрос будет один:
    [sql]SELECT * FROM shop WHERE categoryid=$id ORDER BY title LIMIT 0,20[/sql]
    Все просто и удобно - выбрали 20 товаров, каждая строка результата хранит все данные товара, никаких дополнительных телодвижений. А в случае связок сколько будет запросов и каких, и как все это выводить? Вот же он, геморрой, во всей своей красе.

    Хех. Какие же тут все... одностороннеориентированные ;)
     
  8. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Если нужна производительность, то однозначно горизонтальное расширение. В объектом подходе столкнёшься с тем, что сортировку по доп. полям нормально не сделать, а выборка будет представлять из себя кучу джоинов таблицы самой на себя. Если же доп. поля нужны только для описания характеристик, то я бы предпочёл объектную модель.
     
  9. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Kreker
    в чем ты такую схему рисовал?
     
  10. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Koc
    Я поставил Mysql workbench, но пока ставился третий фреймворк, я не вытерпел и нарисовал в фотошопе)
     
  11. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Kreker
    Все же прошу привести примеры запросов для твоего варианта (задача та же - выборка N товаров из одной категории магазина для отображения страницы каталога), просто чтобы сравнить... все познается в сравнении...
     
  12. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Запроса два: первый выбирает товары, второй свойства. Я думаю, понять, как выбираются товары таким методом для тебя не составит труда.
    Касаемо такой реализации - я от нее отказался в пользу product_options
    id product_type product_id name value
     
  13. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Kreker
    Пожалуйста, конкретный запрос (запросы), чтобы я мог оценить работоспособность и скорость.
    На пальцах всем все и так понятно; но на пальцах магазин работать не будет. Я привел конкретный пример, сделай то же самое плиз.
    В частности, интересует, что будет в WHERE во втором запросе.

    UPD: А еще очень настораживает фраза "куча джоинов таблицы самой на себя"... в общем жду пример :(
     
  14. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Что-то типа этого
    [sql]
    SELECT `products`.`name`, `product_types`.`name` as `category`
    FROM `products`, `product_types`
    WHERE `products`.`product_type`=`product_types`.`id`
    ORDER BY `category` /* Выборка продуктов */

    SELECT `options`.`value`, `type_options`.`name`
    FROM `type_options`, `options`
    WHERE `type_options`.`product_type` IN ('.implode(",", $products_type).')
    AND `options`.`product_id` IN ('.implode(",", $products_id).')
    AND `options`.`opt_id`=`type_options`.`id`
    ORDER BY `type_options`.`product_type` /* Выбираем свойства */
    [/sql]
     
  15. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Kreker
    Спасибо. Замечания:
    1. Первый запрос случаем не всю таблицу выбирает? Конкретных условий типа "catid=123" вообще не видно...
    2. Второй запрос представляется очень тормозным.
    3. Имхо, достаточно одного имплода - по $products_id. (Молодец, что без подзапросов :))
    4. У тебя получается, что второй запрос возвращает в куче свойства сразу для всех выбранных товаров, причем свойства эти отсортированы не в том же порядке, что и товары, т.е. они перемешаны. Как планируешь отображать свойства товаров на странице? (можно на пальцах)
     
  16. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    так-с, вопросище такой. Что лучше, более производительней:

    PHP:
    1.  
    2. <?php
    3. $str = 'некое множество чисел через запятую';
    4.        
    5.             $sql = "SELECT
    6.                 tt_at_text.id, tt_at_text.value_default,
    7.                 tt_at_textarea.id, tt_at_textarea.value_default,
    8.                 tt_at_boolean.id, tt_at_boolean.value_default
    9.             FROM tt_at_text, tt_at_textarea, tt_at_boolean
    10.             WHERE
    11.                 tt_at_text.id IN (%s) OR tt_at_textarea.id IN (%s) OR tt_at_boolean.id IN (%s)";
    12.             $sql = sprintf($sql, $str, $str, $str);
    13.             $result = $db->query($sql);
    14.             while($row = $db->fetchrow($result)) {
    15.                 $defval[$row['id']] = $row['value_default'];
    16.             }
    17.            
    18.             /*
    19.             $sql = "SELECT id, value_default FROM tt_at_text WHERE id IN (%s)";
    20.             $sql = sprintf($sql, $str);
    21.             $result = $db->query($sql);
    22.             while($row = $db->fetchrow($result)) {
    23.                 $defval[$row['id']] = $row['value_default'];
    24.             }
    25.  
    26.             $sql = "SELECT id, value_default FROM tt_at_textarea WHERE id IN (%s)";
    27.             $sql = sprintf($sql, $str);
    28.             $result = $db->query($sql);
    29.             while($row = $db->fetchrow($result)) {
    30.                 $defval[$row['id']] = $row['value_default'];
    31.             }
    32.  
    33.             $sql = "SELECT id, value_default FROM tt_at_boolean WHERE id IN (%s)";
    34.             $sql = sprintf($sql, $str);
    35.             $result = $db->query($sql);
    36.             while($row = $db->fetchrow($result)) {
    37.                 $defval[$row['id']] = $row['value_default'];
    38.             }
    39.             */
    40. ?>
    41.  
    закомментированный вариант или раскомментированный?

    как еще можно улучшить такой запрос?
     
  17. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Koc
    Создай тестовую таблицу, забей ее тестовыми данными, и замерь сам, в чем проблема. На первый взгляд не определить, а заниматься мартышкиным трудом за тебя неохота ;)

    Я бы сказал, оба варианта плохи. Что выборка однотипных данных из трех разных таблиц плохо, что объединение их в один мега-гемор-запрос, чтобы сэкономить количество mysql_query(), тоже плохо. Здесь беда в кривом проектировании таблиц.

    UPD: Первый запрос, кстати, будет работать неверно. Нет условий, связывающих записи из разных таблиц друг с другом, поэтому строки будут множиться друг на друга. Если в первой таблице 10 записей, подходящих под условие $str, во второй 20, в третьей 30, то ты получишь не 60 записей в результате, а 10*20*30=6000. Изучайте теорию SQL ;)
     
  18. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    ну по идее у меня там данные не будут пересекаться. Пока все норм.
     
  19. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Dagdamor
    все-таки я неправ.

    запрос
    [sql]
    SELECT
    tt_at_text_v.aid, tt_at_text_v.value,
    tt_at_textarea_v.aid, tt_at_textarea_v.value,
    tt_at_boolean_v.aid, tt_at_boolean_v.value
    FROM tt_at_text_v, tt_at_textarea_v, tt_at_boolean_v
    WHERE tt_at_text_v.gid=1 OR tt_at_textarea_v.gid=1 OR tt_at_boolean_v.gid=1[/sql]

    выводит кучу данных

    как связывать записи из разных таблиц друг с другом?
     
  20. В твоем случае их не надо связывать надо просто :
    [sql]SELECT tt_at_text_v.aid aid, tt_at_text_v.value FROM tt_at_text_v WHERE tt_at_text_v.gid=1
    UNION
    SELECT tt_at_textarea_v.aid aid, tt_at_textarea_v.value FROM tt_at_textarea_v WHERE tt_at_textarea_v.gid=1
    UNION
    SELECT tt_at_boolean_v.aid aid, tt_at_boolean_v.value FROM tt_at_boolean_v WHERE tt_at_boolean_v.gid=1[/sql]

    Это будет самый быстрый вариант.
     
  21. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    флоппик
    ага, благодарствую
     
  22. Denis

    Denis Активный пользователь

    С нами с:
    5 фев 2006
    Сообщения:
    92
    Симпатии:
    0
    Адрес:
    Украина, Одесса
    я с другой стороны подошёл =))

    Таблица товаров =)

    id | pid | uid | title | options | s_desc | l_desc

    id - ID товара =)
    pid - ID родителя
    uid - артикул
    title - наименование
    s_desc - короткое описание (можно убрать)
    l_desc - полное описание (можно убрать)

    options - а в options храним вещи вида:

    [characteristics]Спецификация:[/characteristics]
    или
    [characteristics]Свойства:[/characteristics]
    или
    [characteristics]Характеристики:[/characteristics]

    дальше
    [property:[Вес]]10кг[/property]
    [property:[Длина]]100см[/property]
    [property:[Запах]]плохой[/property]

    свойство причем к каждой единице можно задать уникальные свойства + на основе этой системы можно понаписывать Мастеры которые будут создавать весовые товары, штучные и т.д.
     
  23. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Denis
    А искать по таким характеристикам как?
     
  24. Denis

    Denis Активный пользователь

    С нами с:
    5 фев 2006
    Сообщения:
    92
    Симпатии:
    0
    Адрес:
    Украина, Одесса
    можно ряд примеров =)?
     
  25. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Denis
    Надо найти товар не длиннее 100 см, от которого хорошо пахнет. :lol: