powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация group by при объединении таблиц
5 сообщений из 5, страница 1 из 1
Оптимизация group by при объединении таблиц
    #40096977
Ekzis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, существует 3 таблицы. Таблица product
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
CREATE TABLE IF NOT EXISTS `oc_product` (
  `product_id` int NOT NULL,
  `model` varchar(64) NOT NULL,
  `sku` varchar(64) NOT NULL,
  `upc` varchar(12) NOT NULL,
  `ean` varchar(14) NOT NULL,
  `jan` varchar(13) NOT NULL,
  `isbn` varchar(17) NOT NULL,
  `mpn` varchar(64) NOT NULL,
  `location` varchar(128) NOT NULL,
  `quantity` int NOT NULL DEFAULT '0',
  `stock_status_id` int NOT NULL,
  `image` varchar(255) DEFAULT NULL,
  `manufacturer_id` int NOT NULL,
  `shipping` tinyint(1) NOT NULL DEFAULT '1',
  `price` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `points` int NOT NULL DEFAULT '0',
  `tax_class_id` int NOT NULL,
  `date_available` date NOT NULL DEFAULT '1990-09-02',
  `weight` decimal(15,3) NOT NULL DEFAULT '0.000',
  `weight_class_id` int NOT NULL DEFAULT '0',
  `length` decimal(15,8) NOT NULL DEFAULT '0.00000000',
  `width` decimal(15,8) NOT NULL DEFAULT '0.00000000',
  `height` decimal(15,8) NOT NULL DEFAULT '0.00000000',
  `length_class_id` int NOT NULL DEFAULT '0',
  `subtract` tinyint(1) NOT NULL DEFAULT '1',
  `measure` varchar(64) DEFAULT NULL,
  `inlay` varchar(255) DEFAULT NULL,
  `minimum` int NOT NULL DEFAULT '1',
  `sort_order` int NOT NULL DEFAULT '0',
  `status` tinyint(1) NOT NULL DEFAULT '0',
  `viewed` int NOT NULL DEFAULT '0',
  `date_added` datetime NOT NULL,
  `date_modified` datetime NOT NULL,
  `noindex` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`product_id`),
  KEY `manufacturer_id` (`manufacturer_id`),
  KEY `model` (`model`),
  KEY `image_price_quantity_status` (`image`,`price`,`quantity`,`status`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;



Таблица attribute
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TABLE IF NOT EXISTS `oc_attribute` (
  `attribute_id` int NOT NULL AUTO_INCREMENT,
  `attribute_group_id` int NOT NULL,
  `name` varchar(32) NOT NULL,
  `value` varchar(32) NOT NULL,
  `sort_order` int NOT NULL,
  PRIMARY KEY (`attribute_id`),
  KEY `attribute_id_name_value` (`attribute_id`,`name`,`value`)
) ENGINE=InnoDB AUTO_INCREMENT=383 DEFAULT CHARSET=utf8mb3;



Таблица product_attribute
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE IF NOT EXISTS `oc_product_attribute` (
  `product_id` int NOT NULL,
  `attribute_id` int NOT NULL,
  `language_id` int NOT NULL,
  `text` text NOT NULL,
  PRIMARY KEY (`product_id`,`attribute_id`,`language_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;



Необходимо выбрать атрибуты, которые подходят под фильтр, реализовано это таким образом
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
SELECT DISTINCT
    a.attribute_id attribute_id,
    a.name,
    a.value
FROM
    oc_product AS p
LEFT JOIN
    oc_product_attribute AS pa
ON
    (p.product_id = pa.product_id)
LEFT JOIN
    oc_attribute AS a
ON
    (
        pa.attribute_id = a.attribute_id
    )
WHERE
     p.image IS NOT NULL AND p.price > 0 AND p.quantity > 0 AND p.status > 0  



Если ставми LIMIT 25, то запрос выполняется быстро, если LIMIT 100, то запрос замедляется более чем в 10 раз. Проблема заключается в том, что атрибуты мы должны выбрать все, но скорость очень сильно падает.

План запроса
Код: sql
1.
2.
3.
1	SIMPLE	p		range	image_price_quantity_status	image_price_quantity_status	768		20678	3.70	Using where; Using index; Using temporary	
1	SIMPLE	pa		ref	PRIMARY	PRIMARY	4	dev_shop.p.product_id	5	100.00	Using index	
1	SIMPLE	a		eq_ref	PRIMARY,attribute_id_name_value	PRIMARY	4	dev_shop.pa.attribute_id	1	100.00		



Записей в product > 40000, attribute 380, product_attribute > 250000 и база будет расти.

В качестве СУБД использую MySQL 8.0.26.

Не могли бы вы подсказать в чем может быть проблема(Долго выполняется запрос) и как его оптимизировать?
...
Рейтинг: 0 / 0
Оптимизация group by при объединении таблиц
    #40096986
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во-первых, запрос какой-то жестокий и бессмысленный... какой великий смысл выбирать только атрибуты, да с возможным дублированием, да с возможными NULL, да ещё и LIMIT без сортировки... и при этом не смотреть, к какому продукту они относятся.

Во-вторых, а почему в структуре нет FK?

В третьих, какой может быть физический смысл у нулевой цены?

На самом деле вопросов гораздо больше...
...
Рейтинг: 0 / 0
Оптимизация group by при объединении таблиц
    #40096992
Ekzis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

Мы выводим динамически меню, которое включает в себя атрибуты, а атрибуты получаем на основе тех продуктов, которые есть в наличии и в которых есть цена и изображение.
То есть в условие where приходят product_id, к которым нужно получить атрибуты. Получить нужно только атрибуты, подходящие к этим product_id
...
Рейтинг: 0 / 0
Оптимизация group by при объединении таблиц
    #40097033
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ekzis , ну тогда сразу - заменить LEFT JOIN на INNER и добавить DISTINCT.

Далее - разбираемся с AND p.price > 0 AND p.quantity > 0 AND p.status > 0 .

1) price может быть нулём? может быть NULL?
2) status - некий ограниченный фиксированный набор значений? если да - укажите его.

Дальше. Создайте индексы oc_product (product_id, image, price, quantity, status) и oc_product (image, product_id, price, quantity, status) . Посмотрите в плане, будет ли какой-то из них использоваться, если да - оставьте его.
...
Рейтинг: 0 / 0
Оптимизация group by при объединении таблиц
    #40097503
Ekzis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina, спасибо, но скорости пока не прибавилось.

На счет price, есть продукты, где он должен быть равен именно 0.

Индексы создал, в приоритете использует тот, который был изначально. Если его убрать, то каждый индекс, который вы посоветовали используется, но скорости он, к сожалению, не дает
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация group by при объединении таблиц
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]