2012-09-18 64 views
0

我花了几个小时来制作一个SQL查询,该查询执行一个JOIN并将两列排序在一起,以我以前没有处理的方式。下面是该查询:加入/排序缓慢运行

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的每一行都有一个直接在表中引用的“主要”类别,以及存储在merchant_category表中的零个或多个“辅助”类别。现在它可以正常工作,但速度很慢:通常会在我的生产数据库上超过一分钟。我想JOIN加上复杂的排序是造成这个问题,但我能做什么?

编辑下面是这两个表的模式:

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`) 
) 
+0

您可以发布表的架构专门'merchant'和'merchant_category'?也许你错过了一些索引.. –

+0

你有索引设置正确吗?两个表中有多少行? – Erik

+0

@Erik'商家'有超过20,000我相信,'merchant_category'有几倍。 – Jonah

回答

2

尝试添加第二表的外键约束,

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`) 
) 
+0

@Jonah你想排序什么? –

+0

由两个不同表中的优先级号码组成。在主要类别的“merchant”表中,以及次要类别的“merchant_category”表中。 – Jonah

+0

好吧,我添加了外键约束,我希望我的查询现在能更快运行吗? – Jonah

1

你强迫它运行LEAST的每一行,以便对它进行排序(两次!)。它不能为此使用索引。

+0

你会推荐什么作为替代方案? – Jonah

+0

我不得不使用'LEAST'来整合这两个数字,以便将它们整理在一起。 – Jonah

+0

另外两个小评论。 'merchant_category'.'category_id' ='2''是不是'JOIN'的一部分?你应该有一个组合索引,包括你选择的东西和主键,所以(primary_category_id,id)。一个'EXPLAIN'会在该表上显示一个表扫描... –