|
|
|
|
|
для: sanekdi
(05.11.2012 в 18:36)
| | Не забудьте, плиз! Будет интересно узнать! =) | |
|
|
|
|
|
|
|
для: Sfinks
(05.11.2012 в 18:15)
| | Единственное, что приходит в голову - сделать таблицу типом MEMORY.
Если включить профилирование запроса - видно, что 75% времени тратится на открытие таблиц, т.е. на чтение данных с диска.
При переключении с MyISAM на MEMORY это значение падает до 6%.
И общее время выполнения скрипта (с представленным дампом) падает с 2.5 милисекунд, до 0.67
Но это только при первом обращении.
Если подобные запросы выполняются постоянно, то таблица постоянно в кеше и время выполнения и там и там нивелируется к ~0.5мс. | |
|
|
|
|
|
|
|
для: Sfinks
(05.11.2012 в 18:15)
| | Спасибо, за ответ ))) меня остановило наличие количество конструкции join, реально их может быть до 50, я задумался о структуре БД вообще правильная ли она? Сейчас вы меня успокоили я реально попробую данную структуру на сервере, после этого отпишусь Вам тормозит сервер БД или нет. | |
|
|
|
|
|
|
|
для: sanekdi
(05.11.2012 в 17:29)
| | Вопрос. Вы реально видите, что такие запросы грузят серв? Или вам кажется что тут много джойнов и серверу будет тяжело?
Единственное, что в этом запросе лишнее - Это DISTINCT.
У вас в shop_product_attribute_value все 3 поля - это PK, а следовательно уникальны. Следовательно при умножении shop_product на shop_product_attribute_value с WHERE по всем 3ем полям дублей никак не появится.
В остальном все нормально и EXPLAIN запроса выглядит очень красиво.
Возможно вам запрос кажется сильно тяжелым, т,к. вы не совсем правильно понимаете ход его работы?
Этот же запрос можно изобразить более логично:
SELECT a.* FROM shop_product a
JOIN shop_product_attribute_value a1 ON a.id_product=a1.id_product AND a1.id_attribute=1 AND a1.id_value=1
JOIN shop_product_attribute_value a2 ON a.id_product=a2.id_product AND a2.id_attribute=3 AND a2.id_value=8
JOIN shop_product_attribute_value a3 ON a.id_product=a3.id_product AND a3.id_attribute=2 AND a3.id_value=5
|
Смотрите. целые таблицы не перемножаются. Перемножаются обмылки от них, тем самым еще больше смыливаясь.
При чем все фильтры по PK.
В эксплэйне вообще в каждом подзапросе по 1 строке остается.
А в результате 1*1*1*1=1.
Ну допустим тут дамп маленький.
Допустим в реале у вас от А1 останется 200 строк.
Джойним их к А и снова в результате 200 строк.
От А2 останется пусть 300 строк.
Джойним их к А. Но у нас же INNER JOIN, а не CROSS JOIN. Следовательно результат еще уменьшается. Уже 70 строк остается.
Потом тоже с А3. | |
|
|
|
|
|
|
|
для: Sfinks
(05.11.2012 в 16:59)
| | Вот запрос, по нему вернется флешка 2гб, белого цвета, весом 80гр
/*<?*/
SELECT DISTINCT shop_product.*
FROM `shop_product_attribute_value` AS a1
INNER JOIN `shop_product` USING(id_product)
INNER JOIN `shop_product_attribute_value` AS a2 USING(id_product)
INNER JOIN `shop_product_attribute_value` AS a3 USING(id_product)
WHERE
a1.id_attribute=1 AND a1.id_value=1 AND
a2.id_attribute=3 AND a2.id_value=8 AND
a3.id_attribute=2 AND a3.id_value=5
|
Такой тип запроса, предполагает много join - ов и join будет больше в зависимости чем больше будет атрибутов и выбранных в них значений, но другая структура БД в голову не приходит, может подскажите? | |
|
|
|
|
|
|
|
для: sanekdi
(05.11.2012 в 15:21)
| | > Суть проблемы: возникает сложные запросы для выборки товаров по атрибутам и их значениям
Это плата за универсальность. Запросы по любому будут сложные.
К сожалению я пока на практике не пользовался такой структурой.
Может вы приведете пример сложного запроса, который особо нагружает БД?
Может он кроме того что сложен еще и неправильно составлен.... | |
|
|
|
|
|
|
| Есть магазин в котором много разных типов товара.
У каждого товара есть атрибутов и различные значения
Таблица атрибутов
/*<?*/
CREATE TABLE IF NOT EXISTS `shop_attributes` (
`id_attribute` int(11) NOT NULL AUTO_INCREMENT,
`name_attribute` varchar(128) NOT NULL,
`type_input` enum('select','checbox') NOT NULL DEFAULT 'select',
PRIMARY KEY (`id_attribute`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
--
-- Dumping data for table `shop_attributes`
--
INSERT INTO `shop_attributes` (`id_attribute`, `name_attribute`, `type_input`) VALUES
(1, 'Память', 'select'),
(2, 'Вес', 'select'),
(3, 'Цвет', 'select');
|
Таблица значений атрибутов
/*<?*/
CREATE TABLE IF NOT EXISTS `shop_attribute_value` (
`id_value` int(11) NOT NULL AUTO_INCREMENT,
`attribute_value` varchar(128) NOT NULL,
PRIMARY KEY (`id_value`),
UNIQUE KEY `attributte_value` (`attribute_value`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ;
--
-- Dumping data for table `shop_attribute_value`
--
INSERT INTO `shop_attribute_value` (`id_value`, `attribute_value`) VALUES
(1, '2гб'),
(2, '4гб'),
(3, '8гб'),
(4, '16гб'),
(5, '80 гр'),
(6, '120 гр'),
(7, 'Черный'),
(8, 'Белый'),
(9, 'Сниний'),
(10, 'красный');
|
таблица связей атрибутов и значений
/*<?*/
CREATE TABLE IF NOT EXISTS `shop_attribute_to_value` (
`id_attribute` int(11) NOT NULL,
`id_value` int(11) NOT NULL,
PRIMARY KEY (`id_attribute`,`id_value`),
KEY `id_attribute` (`id_attribute`),
KEY `id_value` (`id_value`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Dumping data for table `shop_attribute_to_value`
--
INSERT INTO `shop_attribute_to_value` (`id_attribute`, `id_value`) VALUES
(1, 1),
(1, 2),
(1, 3),
(1, 4),
(2, 5),
(2, 6),
(3, 7),
(3, 8),
(3, 9),
(3, 10);
|
таблица товаров
/*<?*/
CREATE TABLE IF NOT EXISTS `shop_product` (
`id_product` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`meta_k` varchar(255) NOT NULL,
`meta_d` varchar(255) NOT NULL,
`price` float(8,2) NOT NULL,
`new` enum('no','yes') NOT NULL,
`hide` enum('hide','show') NOT NULL,
`date_add` datetime NOT NULL,
PRIMARY KEY (`id_product`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `shop_product` (`id_product`, `name`, `title`, `meta_k`, `meta_d`, `price`, `new`, `hide`, `date_add`) VALUES
(1, 'Flash Kingston 2гб', 'Flash Kingston 2гб', '', '', 100.00, 'yes', 'show', '2012-11-05 16:48:37'),
(2, 'Flash Kingston 4гб', 'Flash Kingston 4гб', '', '', 200.00, 'yes', 'show', '2012-11-05 16:49:04'),
(3, 'Flash Matrix 2гб', 'Flash Matrix 2гб', '', '', 120.00, 'yes', 'show', '2012-11-05 16:50:21'),
(4, 'Flash Matrix 4гб', 'Flash Matrix 4гб', '', '', 180.00, 'yes', 'show', '2012-11-05 16:51:31');
|
таблица связей между атрибута, значением атрибутов, и товарами
/*<?*/
CREATE TABLE IF NOT EXISTS `shop_product_attribute_value` (
`id_product` int(11) NOT NULL,
`id_attribute` int(11) NOT NULL,
`id_value` int(11) NOT NULL,
PRIMARY KEY (`id_product`,`id_attribute`,`id_value`),
KEY `id_product` (`id_product`),
KEY `id_value` (`id_value`),
KEY `id_attribute` (`id_attribute`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Dumping data for table `shop_product_attribute_value`
--
INSERT INTO `shop_product_attribute_value` (`id_product`, `id_attribute`, `id_value`) VALUES
(1, 1, 1),
(1, 2, 5),
(1, 3, 8),
(1, 3, 9),
(3, 1, 1),
(3, 2, 6),
(3, 3, 8);
|
При данной структуре каждому товару можно сделать, любые аттрибуты с любыми значения, для разных типов товаров.
Суть проблемы: возникает сложные запросы для выборки товаров по атрибутам и их значениям, т.е. нужно найти flash с атрибутом пямять значение 2гб, цвет - беллый и весом 80г
Получается сложные запросы, перемножением таблицы саму на себя, возникает как оптимизировать структуру БД чтобы не возникали нагрузающие бд запросы, темболее что атриботов и значений может быть много
Буду благодарен кто подскажет в каком напрвлении нужно, двигаться | |
|
|
| |
|