我从昨天早上开始就在和它作斗争,但我仍然无法让它工作得足够快。
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;
这就是 explain 向我展示的内容。
"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 秒。 我知道这是由于订单条款负责一半的时间。
我能做些什么来在不进行重大更改的情况下将我的时间至少减少一半?
最佳答案
您的查询有几个问题。
- 您使用了
LEFT OUTER JOIN
,但在WHERE
子句中您说AND "items_categories"."cat_id"IN(1)
这使得OUTER JOIN
成为一个有效的INNER JOIN
因为"items"
中的每一行在"items_categories"< 中没有对应的记录
将为"items_categories"."cat_id"
返回NULL
并因此被WHERE
子句消除 - 有相当多的博客表明
SQL_CALC_FOUND_ROWS
会对性能产生负面影响;你确定你真的需要它吗? - 我很困惑,您可以执行
GROUP BY "items"."id"
然后使用ORDER BY "items"."artist"ASC, "items"."名称"ASC
。我习惯了 MSSQL,这根本无法编译!?! - 我假设 GROUP BY 在那里,因为 JOIN 会导致“ double ”,因为“项目”类别中的多个记录可能符合要求。如果是这样,您应该使用
WHERE EXISTS
构造而不是进行实际的 JOIN 然后再次对所有内容进行 GROUPing 以摆脱它们。(对于 DISTINCT 也是如此,无论如何它只是一个奇特的 GROUP BY)
因此,我建议:
SELECT "items"."id"
FROM "items"
WHERE "items"."id" > 0
AND "items"."hidden" = 0
AND "items"."deleted" = 0
AND EXISTS ( SELECT *
FROM "items_categories"
WHERE "items_categories"."item_id" = "items"."id"
AND "items_categories"."cat_id" IN (1) )
ORDER BY "items"."artist" ASC, "items"."name" ASC
LIMIT 0, 100;
(这 -- 或多或少 -- 也可以在 MSSQL 中编译 =)
关于mysql - 我怎样才能优化这个查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22631872/