【发布时间】:2017-02-26 17:53:08
【问题描述】:
我需要一些关于我的商店数据库结构的帮助。要从类别中获取项目,已经有一些连接,但我想从其他表中将图像添加到项目中。主项目表没有图像 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
有时,14k 个项目和 40k 个图像最多需要 1 分钟。
有什么可以改进的吗?!请注意,也可能有没有图像的项目。这不是必需的。
少量添加。即使是单个图像加入项目也会使查询运行超过一分钟。这是一个示例:
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
【问题讨论】:
-
请注意,没有 ORDER BY 的 LIMIT 是一个相当没有意义的概念 - 并不是说这对性能有任何帮助。我们可以看到问题查询的 EXPLAIN 吗?
-
@Strawberry 我添加了订单和限制。还是什么都没有。
-
如我所说。请提供解释
-
你可能有一个规则,每列都有一个“评论”,但这很可笑:
description ... COMMENT 'Item description'。
标签: mysql performance join