我从昨天早上就开始打架,但我仍然无法让它快速运转。
items
表的artist
和name
字段为varchar。
所有其他字段都是索引的各种类型的整数。
我已经在两个varchar字段上测试了带或不带索引的查询,但没有变化。
items_categories
有三列:id
,item_id
和cat_id
。
SQL_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秒。 我知道这是由于订单条款负责一半的时间。
在没有重大改变的情况下,我能做些什么来至少减少一半的时间吗?
答案 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,这根本就不会编译!?! 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;
我想你已经创建了正确的索引,不是吗?