Mysql 加入/分类缓慢运行
我花了几个小时制作了一个SQL查询,该查询执行一个Mysql 加入/分类缓慢运行,mysql,sql,join,sql-order-by,Mysql,Sql,Join,Sql Order By,我花了几个小时制作了一个SQL查询,该查询执行一个连接,并将两列排序在一起,这种方式我以前从未处理过。以下是查询: SELECT `m`.`id`, `m`.`primary_category_id`, `m`.`primary_category_priority`, `m`.`description` FROM (`merchant` AS m) LEFT JOIN `merchant_category` ON `merchant_category`.`merchant_id` = `
连接
,并将两列排序在一起,这种方式我以前从未处理过。以下是查询:
SELECT `m`.`id`, `m`.`primary_category_id`, `m`.`primary_category_priority`, `m`.`description`
FROM (`merchant` AS m)
LEFT JOIN `merchant_category`
ON `merchant_category`.`merchant_id` = `m`.`id`
WHERE
`merchant_category`.`category_id` = '2'
OR `m`.`primary_category_id` = '2'
GROUP BY `m`.`id`
ORDER BY
LEAST(merchant_category.priority = 0, `primary_category_priority` = 0) ASC,
LEAST(merchant_category.priority, `primary_category_priority` ) ASC
LIMIT 10
它必须将两列排序在一起,一列来自merchant_category表,另一列来自merchant表,以便将它们排序在一起。商户
的每一行都有一个表中直接提及的“主要”类别,以及存储在商户_类别
表中的零个或多个“次要”类别。现在它工作正常,但速度非常慢:在我的生产数据库上通常超过一分钟。我想是连接
加上复杂的排序造成了这个问题,但是我能做什么呢
编辑以下是两个表的模式:
CREATE TABLE IF NOT EXISTS `merchant` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8 NOT NULL,
`primary_category_id` int(11) NOT NULL,
`primary_category_priority` int(10) unsigned NOT NULL DEFAULT '0',
`description` mediumtext CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `merchant_category` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`merchant_id` int(10) NOT NULL,
`category_id` int(10) NOT NULL,
`priority` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
您强制它对每一行运行
至少(两次!)以便对其进行排序。它无法对此使用索引。您正在强制它对每一行至少运行(两次!),以便对其进行排序。它无法对此使用索引。尝试在第二个表上添加外键约束
CREATE TABLE IF NOT EXISTS `merchant_category` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`merchant_id` int(10) NOT NULL,
`category_id` int(10) NOT NULL,
`priority` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
CONSTRAINT mc_fk FOREIGN KEY (`merchant_id`) REFERENCES `merchant`(`id`)
)
尝试在第二个表上添加外键约束
CREATE TABLE IF NOT EXISTS `merchant_category` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`merchant_id` int(10) NOT NULL,
`category_id` int(10) NOT NULL,
`priority` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
CONSTRAINT mc_fk FOREIGN KEY (`merchant_id`) REFERENCES `merchant`(`id`)
)
您能否发布表的架构,特别是merchant
和merchant\u category
?也许你错过了一些索引。你的索引设置正确吗?两个表中有多少行?@Erikmerchant
我相信有20000多行,merchant\u category
的行数是原来的几倍。@JohnWoo我添加了表架构。你能具体发布表架构吗merchant
和merchant\u category
?也许你错过了一些索引。你的索引设置正确吗?两个表中有多少行?@Erikmerchant
我相信有20000多行,而merchant\u category
的行数是原来的几倍。@JohnWoo我添加了表架构。您推荐什么替代方案?我必须使用LEAST
将这两个数字进行整合,以便对它们进行排序。另外两个小注释。“merchant\u category
category\u id
=”2“不应该是加入的一部分吗?您应该有一个复合索引,其中包括您选择的对象和主键,因此(primary_category_id,id)。EXPLAIN
会在该表上显示一个表扫描…我不知道它是否会更快,但感觉您应该使用CASE
语句作为SELECT
的一部分来确定优先级,然后按指定的列进行排序。在这种情况下,
语句就是所选的特定类别,它可以是任何类型。您推荐什么作为替代方法?我必须使用最小值
将这两个数字进行集成,以便将它们排序在一起。另外两个小注释。“merchant\u category
category\u id
=”2“不应该是加入的一部分吗?您应该有一个复合索引,其中包括您选择的对象和主键,因此(primary_category_id,id)。EXPLAIN
会在该表上显示一个表扫描…我不知道它是否会更快,但感觉您应该使用CASE
语句作为SELECT
的一部分来确定优先级,然后按指定的列进行排序。其中
语句就是在本例中选择的特定类别,它可以是任何内容。@Jonah您想排序什么?按两个不同表中的优先级编号排序。在主类别的merchant
表中,以及在次要类别的merchant\u category
表中。好的,我添加了外键约束,我是否希望我的查询现在运行得更快?可能与预期的一样。你试着再次运行查询了吗?哇,这让查询速度加快了很多,现在基本上是即时的。谢谢@约拿:你想排序什么?按两个不同表中的优先级编号排序。在主类别的merchant
表中,以及在次要类别的merchant\u category
表中。好的,我添加了外键约束,我是否希望我的查询现在运行得更快?可能与预期的一样。你试着再次运行查询了吗?哇,这让查询速度加快了很多,现在基本上是即时的。谢谢