mysql - 我怎样才能优化这个查询

标签 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;

这就是 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/

相关文章:

php - 如何使用 Fabrik(joomla 组件)表单连接到数据库表并搜索匹配并返回结果?

mysql - sql 按年和月计数,即使为零也显示月份

python - Python 3.3 的线性规划优化包?

sql-server - 如何比较两个查询?

php - PHP 或 SQL 中耗时格式

c# - 使用 DSN ODBC 从多台远程计算机连接到 ONLINE MySQL 数据库

optimization - 检索从 SIFT/SURF 获得的最重要的特征

optimization - Intel Skylake 的统一调度器与 AMD Zen 的单独调度器

mysql - 优化 DISTINCT 。在 mysql 中从一个大的 Mysql 表

mysql - 在 SQL 中有效地加入间隔范围