В данном обзоре будет четыре, если так можно выразиться, архитектурных паттерна для построения базы данных интернет-магазина. Структура будет затрагивать лишь каталог товаров и речь пойдёт в целом об архитектуре, не делая акцента на какой-либо конкретной СУБД, хотя если примеры запросов встретятся, то они будут на основе MySQL. Стоит также учитывать, что у каждой СУБД может быть своя реализация каких-либо решений, отсутствующая в других СУБД.
Возьмём за основу абстрактный интернет-магазин со множеством товаров от ноутбуков и стиральных машин до кофемолок. У каждого типа товара будет свой набор свойств (атрибутов или характеристик). Естественно, что у пользователя должна быть возможность сортировать и фильтровать товары по их свойствам, например по цене, весу, высоте, ширине, мощности и пр. (яркий пример: Яндекс.Маркет – система выбора разнообразных товаров).
Общий пример структуры ИМ
Интернет-Магазин продаёт комплектующие к ПК (жёсткие диски, оперативную память, видео карты и т.д). Очевидно, что для каждого типа будет индивидуальный набор характеристик, а для некоторых характеристики будут совпадать. Так, например, у жёстких дисков будет следующий набор атрибутов: интерфейс, буфер, скорость вращения шпинделя. Для оперативной памяти он будет несколько иной: тип памяти, тактовая частота, объём. Но для всех типов товаров будут также и общие характеристики, такие как: наличие на складе, цена и производитель.
С какой основной проблемой мы встретимся? Клиент (он же заказчик интернет магазина) хочет, чтобы у него был по максимуму гибко настраиваемый каталог товаров. Т.е., если вдруг, клиент начнёт продавать фотоаппараты, то, очевидно, он не захочет снова нанимать для этого программистов. И это желание вполне закономерно. Заказчик должен просто зайти в админ-панель, создать новый тип товара “Фотоаппараты”, задать для этого типа набор своих характеристик и всё – товар готов к продаже в интернет-магазине. Вот эту гибкость нам и нужно реализовать.
Постараемся рассмотреть если не все варианты реализации, то самые основные и ходовые. Ну и, как обычно, плюсы-минусы и вывод.
- EAV
- One table
- Flat tables
- Документо-ориентированная база данных
Пример структуры EAV
1. EAV EAV расшифровывается как Entity–attribute–value или по-русски: объект-атрибут-значение. Она представляет собой модель данных для описания сущностей, в которых количество атрибутов (свойств, параметров) может быть потенциально большим. Entity – это своего рода “элемент данных”, например, категории товаров или сам товар. Attribute – это атрибуты товара, например: название, описание, цена и так для каждого из типов товаров. И value представляет собой реальное значение, принадлежащее атрибуту. Упрощенная схема БД будет выглядеть следующим образом: Схема EAV ProductEntity – таблица описывающая сущности. ProductAttribute – таблица описывающая атрибуты сущностей. AttributeValue – таблица, содержащая значения атрибутов.
Данное решение позволяет довольно легко и непринуждённо изменять (добавлять, удалять или редактировать) набор параметров сущности.
Но очевидны и недостатки: значением атрибута будет являться только строковый тип, в нашем случае – это text, из этого следует то, что придётся преобразовывать типы. К тому же, работа со строками медленнее и затратнее в БД. Помимо этого, у нас могут появиться повторы для названий атрибутов.
Можно несколько усложнить, но, в какой-то мере, и улучшить нашу структуру. Добавим для каждого типа атрибута свою таблицу (под типом атрибута я подразумеваю: целочисленные значения, строковые значения, числа с плавающей точкой и пр.).
Структура EAV Т.о. значения атрибутов у нас будут хранится в отдельных таблицах значений, причём разбиты они будут по типам, т.е. атрибуты со строковыми значениями будут хранится в таблице строковых атрибутов, а значения атрибутов с целыми числами – будут храниться в таблице с целочисленными значениями атрибутов и т.д.
Минусы: сложные и ресурсоёмкие запросы к таблицам отсюда тормоза, причём, если без кеширования и при большом количестве атрибутов – это могут быть очень сильные тормоза; трудности при масштабировании; трудность в обеспечении целостности данных.
Плюсы: универсальность; гибкость и относительная простота при добавлении\удаление\редактирование характеристики товара.
Когда стоит применять? Всё исходя из плюсов: если характеристики для товаров очень динамичны и часто изменяются.
Заметки на полях. EAV используется, пожалуй, в одном из самых распространённых решений для создания интернет-магазина – Magento. Довольно занятная презентация Билла Карвина об антипаттернах в MySQL и EAV в том числе.
Пример структуры One table
2. One table Это наиболее типичный и простой вариант архитектурного решения, для небольшого интернет-магазина со скромным количеством типов продаваемых товаров и практически не изменяемым набором атрибутов. Суть его заключается в следующем: для ВСЕХ типов товаров существует только одна таблица. Т.о. характеристики для жёстких дисков, оперативной памяти и пр. будут храниться в одной единственной таблице, а неиспользуемые поля, например, интерфейс, буфер, скорость вращения шпинделя – для оперативной памяти будут “забиваться” NULL значениями.
Минусы: сложность администрирования; избыточность данных; неудобство добавления\редактирования товаров.
Плюсы для этого решения описать сложно. Их скорее нет. Больше всего подойдёт в тех случаях, если набор характеристик товаров отличается не значительно.
Пример структуры Flat tables
3. Flat tables Этот способ заключается в том, что для каждого типа товара (фотоаппараты, мобильные телефоны, косметика и пр.) будет создаваться своя таблица. И если понадобится добавить, изменить или удалить поле, то это будет осуществляться при помощи SQL-запросов, например: ALTER TABLE `my_table` ADD `my_field` TINYINT( 1 ) NOT NULL DEFAULT ‘0’; или ALTER TABLE `my_table` DROP `my_field`;
При добавлении или удалении атрибута (alter table) необходимо изменять структуру таблицы, что при большом количестве записей может осуществляться очень долгое время и блокировать на это время таблицу.
Особенно “страшна” для нас блокировка таблиц, т.к. это, по сути, приведёт к остановке работоспособности магазина и, следовательно, к потере денег. Хотя, конечно, есть различные варианты решения данной проблемы. Например, создание временной копии таблицы, с которой и проделаем нужные операции по изменению структуры – это хоть и будет нагружать сервер, но не заблокирует основную таблицу на чтение, с которой работают пользователи магазина. Отмечу, что необходимо устанавливать блокировку на запись для таблицы с товарами, чтобы предотвратить добавление, а, следовательно, и потерю новых данных до того, как мы создадим полную копию таблицы и сделаем из неё основную.
Как дополнение, можно общий набор атрибутов хранить в отдельной таблице, но к магазину, торгующему очень разношерстными товарами – это не поможет. Дело в том, что для одной группы товаров будет один общий набор характеристик, для другой группы – другой набор, причём эти наборы могут пересекаться. Таким образом мы только усложним всё.
Минусы: полная блокировка таблиц; потенциально долгий процесс по изменению структуры таблицы; требует бОльших вычислительных ресурсов на сервере.
4. Документо-ориентированная база данных Этот вариант решения проблемы с возможность добавления\удаления сущностей не на основе реляционной СУБД типа MySQL, MSSQL и подобных, а на основе документо-ориентированных СУБД, типа CouchDB или MongoDB.
Подробный рассказ о документо-ориентированной базе и её различиях с классической реляционной моделью – тема отдельной статьи. Кто захочет сможет найти эту информацию в интернете. Для общего понимания темы, рекомендую прочесть вики. Вариант с ДО базой данных решает множество проблем и ограничений, который нас нас накладывает реляционная модель.
Пример того, как это всё будет выглядеть можно увидеть в документации на офф. сайте монго.
В чем же её основная привлекательность? В быстром и относительно безболезненном добавлении новых сущностей и атрибутов плюс высокая скорость получения данных.
Минусы: это нереляционно; требует значительных затрат времени программистов и администраторов на реализацию программной части для работы интернет-магазина; требует собственный сервер (как минимум VDS), т.к. практически не один shared хостинг не предоставляет эти СУБД.
Плюсы высокая скорость работы.
Какую структуру для интернет-магазина выбрать после прочитанного?
Существует ещё множество различных ньюансов. Например, “Производитель”, является ли он свойством или нужно вынести его в отдельную таблицу. И как поступить правильно – решать исходя из задачи и множества других факторов.
Каков общий вывод я сделал? Всё очень индивидуально. В борьбе за полной универсальностью мы будем терять скорость и увеличивать сложность понимания и создания архитектуры. Всегда нужно исходить из задачи и искать компромиссное решение, которое может быть найдено при детальном анализе. В каких-то случаях лучшим решением будет EAV, в каких-то Flat tables, а где-то можно применить гибридное решение.
Бонус
В качестве бонуса дам ссылку на структуру БД самого большого “конструктора” по построению интернет-магазина – Magento. Посмотреть можно здесь. Надеюсь, данная статья помогла вам в понимании темы или натолкнула на какие-либо продуктивные мысли. Удачного дня!
