如何优化此查询

时间:2014-03-25 10:34:49

标签: mysql optimization query-optimization

我从昨天早上就开始打架,但我仍然无法让它快速运转。

items表的artistname字段为varchar。 所有其他字段都是索引的各种类型的整数。 我已经在两个varchar字段上测试了带或不带索引的查询,但没有变化。

items_categories有三列:iditem_idcat_idSQL_CALC_FOUND_ROWS没有任何影响。

我在两个表中都有65k记录,每个项目都有一个类别,因此items_category表中有一个关系。

罪魁祸首查询。

SELECT SQL_CALC_FOUND_ROWS `items`.`id`
  FROM `items`
    LEFT JOIN `items_categories` ON `items`.`id` = `items_categories`.`item_id`
  WHERE `items`.`id` > 0 AND `items`.`hidden` = 0 AND `items`.`deleted` = 0 AND `items_categories`.`cat_id` IN(1)
  GROUP BY `items`.`id` 
  ORDER BY `items`.`artist` ASC, `items`.`name` ASC
  LIMIT 0, 100;

这就是解释给我看的内容。

"id"    "select_type"   "table" "type"      "possible_keys"                          "key"  "key_len"   "ref"   "rows"  "Extra"
"1"     "SIMPLE"       "items_categories"   "ref"                                    "item_id,cat_id"   "cat_id"    "4" "const" "12152" "Using where; Using temporary; Using filesort"
"1"    "SIMPLE"        "items"  "eq_ref"    "PRIMARY,hidden,deleted,hidden_deleted" "PRIMARY"   "4" "staviny_db.items_categories.item_id"   "1" "Using where"

整个过程需要大约0.2 - 0.3秒。 我知道这是由于订单条款负责一半的时间。

在没有重大改变的情况下,我能做些什么来至少减少一半的时间吗?

3 个答案:

答案 0 :(得分:2)

您的查询存在一些问题。

  • 您使用的是LEFT OUTER JOIN,但在WHERE条款中,您AND "items_categories"."cat_id" IN(1)使OUTER JOIN有效地成为INNER JOIN因为{{1}中的每一行在"items"中没有相应记录的"items_categories"会返回NULL,因此会被"items_categories"."cat_id"条款
  • 删除
  • 有很多博客表明WHERE会对效果产生负面影响;你确定你确实需要吗?
  • 我很困惑你可以SQL_CALC_FOUND_ROWS然后用GROUP BY "items"."id"跟着它。我已经习惯了MSSQL,这根本就不会编译!?!
  • 我假设GROUP BY在那里,因为JOIN会导致'double',因为“items”类别中的多个记录“可能符合要求。如果是这样,你应该使用ORDER BY "items"."artist" ASC, "items"."name" ASC构造而不是做实际的JOIN,然后再次对所有东西进行分组以摆脱它们。(DISTINCT的故事也只是一个奇特的GROUP BY)

因此,我建议:

WHERE EXISTS

(或多或少 - 也会在MSSQL中编译=)

答案 1 :(得分:1)

SELECT SQL_CALC_FOUND_ROWS `items`.`id`
FROM `items`
LEFT JOIN `items_categories` ON `items`.`id` = `items_categories`.`item_id`
WHERE `items_categories`.`cat_id` = 1 AND `items`.`hidden` = 0 AND `items`.`deleted` = 0 
GROUP BY `items`.`id` 
ORDER BY `items`.`artist`, `items`.`name`
LIMIT 0, 100;

答案 2 :(得分:0)

使用group by已经对结果进行了排序,因此您将它们排序两次。也许你只能使用GROUP BY子句:

     SELECT SQL_CALC_FOUND_ROWS `items`.`id`
      FROM `items`
 LEFT JOIN `items_categories` ON `items`.`id` = `items_categories`.`item_id`
     WHERE `items`.`id` > 0 
       AND `items`.`hidden` = 0 
       AND `items`.`deleted` = 0 
       AND `items_categories`.`cat_id` IN(1)
  GROUP BY `items`.`artist` ASC, `items`.`name` ASC, `items`.`id` 
     LIMIT 0, 100;

我想你已经创建了正确的索引,不是吗?