我的商店数据库结构需要一些帮助。要从类别中获取项目,已经有一些连接,但我想从其他表格添加图像到项目。主要项目表没有图像ID,因此我们只需从其他表中获取一个权重= 1。
所以,有一个结构:
CREATE TABLE IF NOT EXISTS `categories` (
`category_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255)
CHARACTER SET utf8mb4 DEFAULT NULL
COMMENT 'Category title',
`parent_id` INT(11) NOT NULL DEFAULT '0'
COMMENT 'Category Parent ID',
`status` TINYINT(1) DEFAULT '0'
COMMENT 'Category active status',
`weight` INT(11) DEFAULT '0',
`slug` VARCHAR(255)
CHARACTER SET utf8mb4 DEFAULT NULL
COMMENT 'Category url alias',
PRIMARY KEY (`category_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `items` (
`item_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255)
CHARACTER SET utf8mb4 NOT NULL DEFAULT ''
COMMENT 'Item name',
`description` TEXT CHARACTER SET utf8mb4 NOT NULL
COMMENT 'Item description',
`user_id` INT(11) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'User id',
`category_id` INT(11) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'Category id',
`price` DECIMAL(10, 2) NOT NULL DEFAULT '0.00'
COMMENT 'Item price',
`status` INT(1) UNSIGNED NOT NULL DEFAULT '1'
COMMENT 'Item status',
`deleted` INT(1) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'Delite status',
`blocked` INT(1) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'Block status',
PRIMARY KEY (`item_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `items_images` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`file` VARCHAR(255)
CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
`weight` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`status` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`deleted` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`created` INT(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci
ROW_FORMAT = COMPACT;
从那里可以看出,类别结构里面还包含parent_id
,所以我们总能得到类别树。
使用此查询也可以正常运行。
SELECT
`i`.*,
`c1`.`name` AS `category_name`,
`c1`.`slug` AS `category_slug`,
`c2`.`name` AS `subcategory_name`,
`c2`.`slug` AS `subcategory_slug`
FROM `items` AS `i`
LEFT JOIN `categories` AS `c2` ON `c2`.`category_id` = `i`.`category_id`
LEFT JOIN `categories` AS `c1` ON `c1`.`category_id` = `c2`.`parent_id`
WHERE `i`.`deleted` = 0 AND `i`.`blocked` = 0 AND `i`.`status` = 1
ORDER BY `i`.`created` DESC
LIMIT 40
但是,如果我加入items_images
喜欢:
SELECT
`i`.*,
`ii`.`file` AS `image`,
`c1`.`name` AS `category_name`,
`c1`.`slug` AS `category_slug`,
`c2`.`name` AS `subcategory_name`,
`c2`.`slug` AS `subcategory_slug`
FROM `items` AS `i`
LEFT JOIN `items_images` AS `ii`
ON `i`.`item_id` = `ii`.`item_id` AND `ii`.`weight` = 1
AND `ii`.`status` = 1 AND `ii`.`deleted` = 0
LEFT JOIN `categories` AS `c2` ON `c2`.`category_id` = `i`.`category_id`
LEFT JOIN `categories` AS `c1` ON `c1`.`category_id` = `c2`.`parent_id`
WHERE `i`.`deleted` = 0 AND `i`.`blocked` = 0 AND `i`.`status` = 1
ORDER BY `i`.`created` DESC LIMIT 40
有时需要花费1分钟才能完成14k项目的40k图像。
有什么我可以改进的吗?!请注意,可能还有没有图像的项目。这不是必需的。
小补充。即使单个图像加入项目也会使查询运行一分钟。这里有一个样本:
SELECT `i`.*, `ii`.`file` AS `image` FROM `items` AS `i`
LEFT JOIN `items_images` AS `ii` ON `i`.`item_id` = `ii`.`item_id`
AND `ii`.`weight` = 1 AND `ii`.`status` = 1 AND `ii`.`deleted` = 0
WHERE `i`.`deleted` =0 AND `i`.`sold` =0 AND `i`.`blocked` =0 AND `i`.`status` = 1
ORDER BY `i`.`created` DESC
答案 0 :(得分:2)
索引parent_id
ALTER TABLE类别ADD INDEX parent_id_ind(parent_id ASC);
尝试再次运行您的查询。
在数据库中,您可以使用索引来提高数据检索的速度。通常在JOIN,WHERE和ORDER BY子句中使用的列上创建索引。
答案 1 :(得分:2)
我建议你改进你的结构,你可以接受或离开它,
我的建议:
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'Category title',
`category_id` int(11) NOT NULL DEFAULT '0' COMMENT 'Category Parent ID',
`status` enum('status1','status2') COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Category active status',
`weight` int(11) DEFAULT '0',
`slug` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'Category url alias',
PRIMARY KEY (`id`),
KEY `category_id_ind` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT 'Item name',
`description` text CHARACTER SET utf8mb4 NOT NULL COMMENT 'Item description',
`user_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'User id',
`category_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Category id',
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT 'Item price',
`status` enum('status1','status2') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'status1' COMMENT 'Item status',
`is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'Delite status',
`is_blocked` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'Block status',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `item_images`;
CREATE TABLE `item_images` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`item_id` int(10) unsigned NOT NULL DEFAULT '0',
`file_path` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL ,
`weight` int(11) unsigned NOT NULL DEFAULT '0',
`status` tinyint(1) unsigned NOT NULL DEFAULT '0',
`is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
`creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT;
答案 2 :(得分:0)
添加复合索引:
items: INDEX(deleted, blocked, status, created) -- created must be last
items_images: INDEX(item_id, weight, status, deleted)
categories: INDEX(category_id, deleted, blocked, status)
除非另有说明,否则列的顺序并不重要。
删除LEFT
,除非您认为有必要。
请提供EXPLAIN SELECT ...
。
迟缓的可能原因是必须检查weight=1
的大量图像行。最重要的是,缺少任何有用的索引意味着进行昂贵的表扫描。