mutineer
Новичок
Оптимизация запроса, эксперты выскажите свое мнение!
Добрый день, вожусь над написанием запроса:
таблицы:
CREATE TABLE `product_rubric` (
`rubric_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`rubric_left` INTEGER(11) UNSIGNED NOT NULL,
`rubric_right` INTEGER(11) UNSIGNED NOT NULL,
`rubric_level` INTEGER(11) UNSIGNED NOT NULL,
`rubric_parent` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`rubric_locked` INTEGER(11) UNSIGNED NOT NULL,
`rubric_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`rubric_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`rubric_has_filters` BINARY(1) NOT NULL DEFAULT '0',
`rubric_import_id` INTEGER(11) UNSIGNED DEFAULT '0',
PRIMARY KEY (`rubric_id`),
UNIQUE KEY `rubric_translit` (`rubric_translit`),
KEY `index_fullbranch` (`rubric_left`, `rubric_right` )
)ENGINE=InnoDB
AUTO_INCREMENT=906 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `vendor_model` (
`model_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`model_rubric_id` INTEGER(11) UNSIGNED NOT NULL,
`model_vendor_id` INTEGER(11) UNSIGNED NOT NULL,
`model_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`model_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`model_status` ENUM('normal','inactive','deleted') NOT NULL DEFAULT 'inactive',
PRIMARY KEY (`model_id`),
UNIQUE KEY `model_translit` (`model_translit`),
KEY `model_rubric_id` (`model_rubric_id`),
KEY `model_vendor_id` (`model_vendor_id`),
CONSTRAINT `model_fk` FOREIGN KEY (`model_rubric_id`) REFERENCES `product_rubric` (`rubric_id`) ON UPDATE CASCADE,
CONSTRAINT `model_fk1` FOREIGN KEY (`model_vendor_id`) REFERENCES `vendor` (`vendor_id`) ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=5 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `product_rubric_relationship` (
`item_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`product_id` INTEGER(11) UNSIGNED NOT NULL,
`rubric_id` INTEGER(11) UNSIGNED NOT NULL,
PRIMARY KEY (`item_id`),
UNIQUE KEY `relationship` (`product_id`, `rubric_id`),
KEY `product_id` (`product_id`),
KEY `rubric_id` (`rubric_id`),
CONSTRAINT `product_rubric_relationship_fk` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `product_rubric_relationship_fk1` FOREIGN KEY (`rubric_id`) REFERENCES `product_rubric` (`rubric_id`) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=62262 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `product` (
`product_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`product_status` ENUM('normal','inactive','deleted') NOT NULL DEFAULT 'normal',
`product_company_id` INTEGER(11) UNSIGNED NOT NULL,
`product_vendor_id` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`product_aliace_id` INTEGER(11) UNSIGNED DEFAULT NULL,
`product_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`product_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`product_image` VARCHAR(255) COLLATE utf8_general_ci DEFAULT '',
`product_short_descr` VARCHAR(500) COLLATE utf8_general_ci DEFAULT '',
`product_price` DECIMAL(11,2) UNSIGNED DEFAULT '0.00',
`product_dt_edit` DATETIME NOT NULL,
`product_photo_cnt` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`product_id`),
UNIQUE KEY `product_translit` (`product_translit`),
KEY `product_profile_id` (`product_company_id`),
KEY `product_aliace_id` (`product_aliace_id`),
KEY `product_profile_name` (`product_company_id`, `product_name`),
KEY `product_vendor_id` (`product_vendor_id`),
CONSTRAINT `product_fk` FOREIGN KEY (`product_company_id`) REFERENCES `company` (`company_id`) ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=9285 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `company` (
`company_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`company_user_id` INTEGER(11) UNSIGNED NOT NULL,
`company_status` ENUM('normal','inactive','deleted') NOT NULL DEFAULT 'inactive',
`company_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`company_type` ENUM('free','standart','premium') NOT NULL DEFAULT 'free',
`company_dt_type` DATE DEFAULT NULL,
`company_region_id` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`company_city_id` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`company_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`company_dt_edit` DATETIME NOT NULL,
PRIMARY KEY (`company_id`),
UNIQUE KEY `company_translit` (`company_translit`),
KEY `company_user_id` (`company_user_id`),
KEY `company_region_id` (`company_region_id`),
KEY `company_city_id` (`company_city_id`),
CONSTRAINT `company_fk` FOREIGN KEY (`company_region_id`) REFERENCES `region` (`region_id`) ON UPDATE CASCADE,
CONSTRAINT `company_fk1` FOREIGN KEY (`company_city_id`) REFERENCES `region_city` (`city_id`) ON UPDATE CASCADE,
CONSTRAINT `profile_fk` FOREIGN KEY (`company_user_id`) REFERENCES `user` (`user_id`) ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=13531 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
Запрос:
Задача. Необходимо получить ветку от заданной ноды, с количеством товаров по каждой рубрике и количеством моделей
различных производителей участвующих в рубрике. На данном этапе товары и модели производителей не пересекаются.
На вход - $node_id - нода, ветку которой надо получить; $region_id - регион пользователя
sql запрос получился такой:
SELECT
RUB.rubric_id,
RUB.rubric_name,
COUNT(DISTINCT MOL.model_id) as model_cnt,
COUNT(DISTINCT REL.product_id) as product_cnt
FROM product_rubric RUB
IGNORE INDEX (index_fullbranch)
LEFT JOIN vendor_model MOL ON MOL.model_rubric_id = RUB.rubric_id
LEFT JOIN product_rubric_relationship REL ON REL.rubric_id = RUB.rubric_id
LEFT JOIN product PRO ON PRO.product_id = REL.product_id
LEFT JOIN company COM ON COM.company_id = PRO.product_company_id AND COM.company_region_id = 11
WHERE (RUB.rubric_left >= 1692)
AND (RUB.rubric_right <= 1709)
GROUP BY RUB.rubric_id
explain:
id sel_typ table type key ref rows Extra
1 SIMPLE RUB index PRIMARY NULL 863 Using where
1 SIMPLE MOL ref rub_id dbname.RUB.rub_id 1 Using index
1 SIMPLE REL ref rub_id dbname.RUB.rub_id 1
1 SIMPLE PRO eq_ref PRIMARY dbname.REL.prod_id 1
1 SIMPLE COM eq_ref PRIMARY dbname.PRO.prod_com_id 1
Время выполнения запроса 141 мс, но при этом product_rubric_relationship и product пустые пока еще.
Если разрешить идекс index_fullbranch, то кол-во рядов в таблице RUB становиться 26, но появляется filesorting, время не меняется, а то и хуже становиться.
Планируется достаточно большой объем (десятки тысяч)
Эксперты дайте пожалуста свое мнение, можно ли использовать такой запрос на основании данных explain или подскажите другую реализацию.
Спасибо
Добрый день, вожусь над написанием запроса:
таблицы:
CREATE TABLE `product_rubric` (
`rubric_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`rubric_left` INTEGER(11) UNSIGNED NOT NULL,
`rubric_right` INTEGER(11) UNSIGNED NOT NULL,
`rubric_level` INTEGER(11) UNSIGNED NOT NULL,
`rubric_parent` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`rubric_locked` INTEGER(11) UNSIGNED NOT NULL,
`rubric_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`rubric_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`rubric_has_filters` BINARY(1) NOT NULL DEFAULT '0',
`rubric_import_id` INTEGER(11) UNSIGNED DEFAULT '0',
PRIMARY KEY (`rubric_id`),
UNIQUE KEY `rubric_translit` (`rubric_translit`),
KEY `index_fullbranch` (`rubric_left`, `rubric_right` )
)ENGINE=InnoDB
AUTO_INCREMENT=906 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `vendor_model` (
`model_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`model_rubric_id` INTEGER(11) UNSIGNED NOT NULL,
`model_vendor_id` INTEGER(11) UNSIGNED NOT NULL,
`model_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`model_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`model_status` ENUM('normal','inactive','deleted') NOT NULL DEFAULT 'inactive',
PRIMARY KEY (`model_id`),
UNIQUE KEY `model_translit` (`model_translit`),
KEY `model_rubric_id` (`model_rubric_id`),
KEY `model_vendor_id` (`model_vendor_id`),
CONSTRAINT `model_fk` FOREIGN KEY (`model_rubric_id`) REFERENCES `product_rubric` (`rubric_id`) ON UPDATE CASCADE,
CONSTRAINT `model_fk1` FOREIGN KEY (`model_vendor_id`) REFERENCES `vendor` (`vendor_id`) ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=5 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `product_rubric_relationship` (
`item_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`product_id` INTEGER(11) UNSIGNED NOT NULL,
`rubric_id` INTEGER(11) UNSIGNED NOT NULL,
PRIMARY KEY (`item_id`),
UNIQUE KEY `relationship` (`product_id`, `rubric_id`),
KEY `product_id` (`product_id`),
KEY `rubric_id` (`rubric_id`),
CONSTRAINT `product_rubric_relationship_fk` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `product_rubric_relationship_fk1` FOREIGN KEY (`rubric_id`) REFERENCES `product_rubric` (`rubric_id`) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=62262 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `product` (
`product_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`product_status` ENUM('normal','inactive','deleted') NOT NULL DEFAULT 'normal',
`product_company_id` INTEGER(11) UNSIGNED NOT NULL,
`product_vendor_id` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`product_aliace_id` INTEGER(11) UNSIGNED DEFAULT NULL,
`product_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`product_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`product_image` VARCHAR(255) COLLATE utf8_general_ci DEFAULT '',
`product_short_descr` VARCHAR(500) COLLATE utf8_general_ci DEFAULT '',
`product_price` DECIMAL(11,2) UNSIGNED DEFAULT '0.00',
`product_dt_edit` DATETIME NOT NULL,
`product_photo_cnt` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`product_id`),
UNIQUE KEY `product_translit` (`product_translit`),
KEY `product_profile_id` (`product_company_id`),
KEY `product_aliace_id` (`product_aliace_id`),
KEY `product_profile_name` (`product_company_id`, `product_name`),
KEY `product_vendor_id` (`product_vendor_id`),
CONSTRAINT `product_fk` FOREIGN KEY (`product_company_id`) REFERENCES `company` (`company_id`) ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=9285 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `company` (
`company_id` INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`company_user_id` INTEGER(11) UNSIGNED NOT NULL,
`company_status` ENUM('normal','inactive','deleted') NOT NULL DEFAULT 'inactive',
`company_translit` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`company_type` ENUM('free','standart','premium') NOT NULL DEFAULT 'free',
`company_dt_type` DATE DEFAULT NULL,
`company_region_id` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`company_city_id` INTEGER(11) UNSIGNED NOT NULL DEFAULT '0',
`company_name` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`company_dt_edit` DATETIME NOT NULL,
PRIMARY KEY (`company_id`),
UNIQUE KEY `company_translit` (`company_translit`),
KEY `company_user_id` (`company_user_id`),
KEY `company_region_id` (`company_region_id`),
KEY `company_city_id` (`company_city_id`),
CONSTRAINT `company_fk` FOREIGN KEY (`company_region_id`) REFERENCES `region` (`region_id`) ON UPDATE CASCADE,
CONSTRAINT `company_fk1` FOREIGN KEY (`company_city_id`) REFERENCES `region_city` (`city_id`) ON UPDATE CASCADE,
CONSTRAINT `profile_fk` FOREIGN KEY (`company_user_id`) REFERENCES `user` (`user_id`) ON UPDATE CASCADE
)ENGINE=InnoDB
AUTO_INCREMENT=13531 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
Запрос:
Задача. Необходимо получить ветку от заданной ноды, с количеством товаров по каждой рубрике и количеством моделей
различных производителей участвующих в рубрике. На данном этапе товары и модели производителей не пересекаются.
На вход - $node_id - нода, ветку которой надо получить; $region_id - регион пользователя
sql запрос получился такой:
SELECT
RUB.rubric_id,
RUB.rubric_name,
COUNT(DISTINCT MOL.model_id) as model_cnt,
COUNT(DISTINCT REL.product_id) as product_cnt
FROM product_rubric RUB
IGNORE INDEX (index_fullbranch)
LEFT JOIN vendor_model MOL ON MOL.model_rubric_id = RUB.rubric_id
LEFT JOIN product_rubric_relationship REL ON REL.rubric_id = RUB.rubric_id
LEFT JOIN product PRO ON PRO.product_id = REL.product_id
LEFT JOIN company COM ON COM.company_id = PRO.product_company_id AND COM.company_region_id = 11
WHERE (RUB.rubric_left >= 1692)
AND (RUB.rubric_right <= 1709)
GROUP BY RUB.rubric_id
explain:
id sel_typ table type key ref rows Extra
1 SIMPLE RUB index PRIMARY NULL 863 Using where
1 SIMPLE MOL ref rub_id dbname.RUB.rub_id 1 Using index
1 SIMPLE REL ref rub_id dbname.RUB.rub_id 1
1 SIMPLE PRO eq_ref PRIMARY dbname.REL.prod_id 1
1 SIMPLE COM eq_ref PRIMARY dbname.PRO.prod_com_id 1
Время выполнения запроса 141 мс, но при этом product_rubric_relationship и product пустые пока еще.
Если разрешить идекс index_fullbranch, то кол-во рядов в таблице RUB становиться 26, но появляется filesorting, время не меняется, а то и хуже становиться.
Планируется достаточно большой объем (десятки тысяч)
Эксперты дайте пожалуста свое мнение, можно ли использовать такой запрос на основании данных explain или подскажите другую реализацию.
Спасибо