Jonah
Jonah

Reputation: 10091

Join/Sort Running Slowly

I spent several hours crafting an SQL query that executes a JOIN and sorts two columns together, in a way that I haven't dealt with before. Here is the query:

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

It has to sort two columns together, one from the merchant_category table, and one from the merchant table, so that they're sorted together. Each row of the merchant has a a "primary" category, referred to directly in the table, and zero or more "secondary" categories, stored in the merchant_category table. Now it works fine, but it's very slow: usually over a minute on my production database. I imagine the JOIN plus the complex sorting is causing the problem, but what can I do?

EDIT Here are the two table's schemas:

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

Upvotes: 0

Views: 81

Answers (2)

John Woo
John Woo

Reputation: 263713

Try to add foreign key constraint on the second table,

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

Upvotes: 2

Alain Collins
Alain Collins

Reputation: 16362

You're forcing it to run LEAST (twice!) for each row in order to sort it. It can't use an index for this.

Upvotes: 1

Related Questions