【问题标题】:Join/Sort Running Slowly加入/排序运行缓慢
【发布时间】:2012-09-18 00:43:11
【问题描述】:

我花了几个小时制作一个 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

它必须将两列排序在一起,一列来自 Mercer_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`)
)

【问题讨论】:

  • 你能把表的架构专门贴出来merchantmerchant_category吗?也许你错过了一些索引..
  • 您是否正确设置了索引?两张表有多少行?
  • @Erik merchant 我相信有超过 20,000 个,merchant_category 有好几倍。
  • @JohnWoo 我添加了表模式。

标签: mysql sql join sql-order-by


【解决方案1】:

尝试在第二张表上添加外键约束,

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

【讨论】:

  • @Jonah 你想排序什么?
  • 按两个不同表中的优先级编号。 merchant 表中的主要类别,merchant_category 表中的次要类别。
  • 好的,我添加了外键约束,我现在应该期望我的查询运行得更快吗?
  • 正如预期的那样,也许。您是否尝试再次运行查询?
  • 哇,速度如此之快,现在基本上是即时的。谢谢!
【解决方案2】:

您强制它为每一行运行LEAST(两次!)以便对其进行排序。它不能为此使用索引。

【讨论】:

  • 您会推荐什么替代方案?
  • 我必须使用LEAST 来整合这两个数字,以便将它们排序在一起。
  • 另外两个小cmets。 'merchant_category.category_id = '2'' 不应该是JOIN 的一部分吗?你应该有一个复合索引,其中包括你选择的东西和主键,所以(primary_category_id,id)。 EXPLAIN 会显示对该表的表扫描...
  • 我不知道它是否会更快,但感觉你应该使用CASE 语句作为SELECT 的一部分来确定优先级 ,然后是 SORT BY 该命名列。
  • WHERE 语句只是在这种情况下选择的特定类别,它可以是任何东西。
猜你喜欢
  • 2013-04-04
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
相关资源
最近更新 更多