Спасибо за ответ, составил такую структуру
Атрибуты двух видов:
1) числовые, для поиска BETWEEN
2) Списки значений
CREATE TABLE `lang` (
`id` tinyint(3) UNSIGNED NOT NULL,
`title` varchar(3) NOT NULL,
`lang_locale` varchar(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `category` (
`id` mediumint(8) UNSIGNED NOT NULL,
`left_key` mediumint(8) NOT NULL,
`right_key` mediumint(8) NOT NULL,
`level` tinyint(3) UNSIGNED NOT NULL,
`parent_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `lang_category` (
`id_category` mediumint(8) UNSIGNED NOT NULL,
`id_lang` tinyint(3) UNSIGNED NOT NULL,
`title` varchar(120) NOT NULL,
`descr` varchar(115) NOT NULL,
`keyw` varchar(115) NOT NULL,
`text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Структура таблицы `attr`, поле type 1 значит числовой, 2 значит список, attr_unit единица измерения
--
CREATE TABLE `attr` (
`id` mediumint(8) UNSIGNED NOT NULL,
`type` tinyint(3) UNSIGNED NOT NULL,
`attr_alias` varchar(255) NOT NULL,
`attr_unit` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Структура таблицы `category_attr`. Связь категорий и атрибутов, в поле status выводить ли в фильтре на странице категории
--
CREATE TABLE `category_attr` (
`id_category` mediumint(8) UNSIGNED NOT NULL,
`id_attr` mediumint(8) UNSIGNED NOT NULL,
`status` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `lang_attr` (
`id_attr` mediumint(8) UNSIGNED NOT NULL,
`id_lang` tinyint(3) UNSIGNED NOT NULL,
`title` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Структура таблицы `products_attr`, в id_attr идентификатор атрибута числового типа
--
CREATE TABLE `products_attr` (
`id_product` int(10) UNSIGNED NOT NULL,
`id_attr` mediumint(8) UNSIGNED NOT NULL,
`attr_val` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Структура таблицы `list_attr`, список атрибутов, в id_attr идентификатор атрибута
--
CREATE TABLE `list_attr` (
`id` mediumint(8) UNSIGNED NOT NULL,
`id_attr` mediumint(8) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `lang_list_attr` (
`id_list_attr` mediumint(9) NOT NULL,
`id_lang` tinyint(4) NOT NULL,
`title` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Структура таблицы `list_attr_products`. связь списка атрибутов и товаров
--
CREATE TABLE `list_attr_products` (
`id_list_attr` mediumint(8) UNSIGNED NOT NULL,
`id_product` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `products` (
`id` int(10) UNSIGNED NOT NULL,
`parent_id` mediumint(8) UNSIGNED NOT NULL,
`articul` varchar(100) NOT NULL,
`brand_id` smallint(5) UNSIGNED NOT NULL,
`first_img_id` int(10) UNSIGNED NOT NULL,
`price` decimal(10,2) UNSIGNED NOT NULL DEFAULT '0.00',
`status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
`show_main_page` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `lang_products` (
`id_product` int(10) UNSIGNED NOT NULL,
`id_lang` tinyint(3) UNSIGNED NOT NULL,
`title` varchar(255) NOT NULL,
`descr` varchar(115) NOT NULL,
`keyw` varchar(115) NOT NULL,
`text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Фильтр товаров
SELECT products.id, products_img.img, products_img.thumb_img, lang_products.title FROM products INNER JOIN lang_products ON lang_products.id_product = products.id INNER JOIN category ON products.parent_id = category.id INNER JOIN products_attr as pr_attr1 ON pr_attr1.id_product = products.id INNER JOIN list_attr_products ON list_attr_products.id_product = products.id LEFT JOIN products_img ON products_img.id = products.first_img_id WHERE pr_attr1.id_attr = 4 AND pr_attr1.attr_val BETWEEN 20 AND 100 AND list_attr_products.id_list_attr IN ('1','2') AND category.id = 3 AND lang_products.id_lang = 2 AND products.status = 1
План запроса:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra
|
+------+-------------+--------------------+--------+-------------------+---------+---------+------------------------------+------+----------+--------------------------+
| 1 | SIMPLE | category | const | PRIMARY | PRIMARY | 3 | const | 1 | 100.00 | Using index
|
| 1 | SIMPLE | pr_attr1 | ref | PRIMARY | PRIMARY | 3 | const | 1 | 100.00 | Using where
|
| 1 | SIMPLE | products | eq_ref | PRIMARY,parent_id | PRIMARY | 4 | qg.pr_attr1.id_product | 1 | 100.00 | Using where
|
| 1 | SIMPLE | list_attr_products | ref | PRIMARY | PRIMARY | 4 | qg.pr_attr1.id_product | 1 | 100.00 | Using where; Using index |
| 1 | SIMPLE | products_img | eq_ref | PRIMARY | PRIMARY | 4 | qg.products.first_img_id | 1 | 100.00 |
|
| 1 | SIMPLE | lang_products | eq_ref | PRIMARY | PRIMARY | 5 | qg.pr_attr1.id_product,const | 1 | 100.00 |
|
Вроде везде используются индексы, не совсем понимаю почему часто не советуют использовать EAV. Скажите пожалуйста, какие могут быть подводные камни и какие есть недочеты в предоставленной выше структуре.
Отредактированно webJunior (11.05.2017 16:57:16)