Если использовать сортировку в оконной функции то очень медленно выполняется запрос, более 20 секунд на массиве данных в 5000 записей. Использую MySQL 8.0.22
Без сортировки 66 мс
select p.product_id as id, JSON_ARRAYAGG(JSON_OBJECT('image', pi.image)) AS images
from oc_product p
left join oc_product_image pi ON pi.product_id = p.product_id
where p.status = 1
group by p.product_id
с сортировкой более 20 секунд.
select p.product_id as id,
JSON_ARRAYAGG(JSON_OBJECT('image', pi.image)) OVER (ORDER BY pi.sort_order) AS images
from oc_product p
left join oc_product_image pi ON pi.product_id = p.product_id
where p.status = 1
group by p.product_id
explain:
-> Window aggregate with buffering: json_arrayagg(json_object('image',pi.image)) OVER (ORDER BY pi.sort_order ) (actual time=12190.707..15578.358 rows=6541 loops=1)
-> Sort: pi.sort_order (actual time=51.189..52.606 rows=6541 loops=1)
-> Table scan on <temporary> (actual time=0.002..0.713 rows=6541 loops=1)
-> Temporary table with deduplication (cost=2996.38 rows=6540) (actual time=46.472..48.014 rows=6541 loops=1)
-> Nested loop left join (cost=2996.38 rows=6540) (actual time=0.029..32.562 rows=6915 loops=1)
-> Filter: (p.`status` = 1) (cost=707.38 rows=6540) (actual time=0.016..17.518 rows=6541 loops=1)
-> Table scan on p (cost=707.38 rows=6656) (actual time=0.014..16.289 rows=6656 loops=1)
-> Index lookup on pi using product_id (product_id=p.product_id) (cost=0.25 rows=1) (actual time=0.002..0.002 rows=0 loops=6541)
индексы есть:
CREATE TABLE `oc_product_image` (
`product_image_id` int NOT NULL AUTO_INCREMENT,
`product_id` int NOT NULL,
`image` varchar(255) DEFAULT NULL,
`sort_order` int NOT NULL DEFAULT '0',
PRIMARY KEY (`product_image_id`),
KEY `product_id` (`product_id`),
KEY `oc_product_image_sort_order_IDX` (`sort_order`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=4986 DEFAULT CHARSET=utf8
CREATE TABLE `oc_product` (
`product_id` int NOT NULL AUTO_INCREMENT,
`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',
`quantity_store_2` 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 '0000-00-00',
`weight` decimal(15,8) NOT NULL DEFAULT '0.00000000',
`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',
`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,
PRIMARY KEY (`product_id`),
KEY `oc_product_sku_IDX` (`sku`) USING BTREE,
KEY `oc_product_status_IDX` (`status`) USING BTREE,
KEY `oc_product_sort_order_IDX` (`sort_order`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=10001061 DEFAULT CHARSET=utf8