mysql GROUP BY 真的慢上一个视图

Posted

技术标签:

【中文标题】mysql GROUP BY 真的慢上一个视图【英文标题】:Mysql GROUP BY really slow on a view 【发布时间】:2019-12-15 00:47:29 【问题描述】:

我有这些表。

CREATE TABLE `movements` (
  `movementId` mediumint(8) UNSIGNED NOT NULL,
  `movementType` tinyint(3) UNSIGNED NOT NULL,
  `deleted` tinyint(1) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `movements`
  ADD PRIMARY KEY (`movementId`),
  ADD KEY `movementType` (`movementType`) USING BTREE,
  ADD KEY `deleted` (`deleted`),
  ADD KEY `movementId` (`movementId`,`deleted`);

CREATE TABLE `movements_items` (
  `movementId` mediumint(8) UNSIGNED NOT NULL,
  `itemId` mediumint(8) UNSIGNED NOT NULL,
  `qty` decimal(10,3) UNSIGNED NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `movements_items`
  ADD KEY `movementId` (`movementId`),
  ADD KEY `itemId` (`itemId`),
  ADD KEY `movementId_2` (`movementId`,`itemId`);

这个视图称为“movements_items_view”。

SELECT 
movements_items.itemId, movements_items.qty,
movements.movementId, movements.movementType
FROM movements_items
JOIN movements ON (movements.movementId=movements_items.movementId
                    AND movements.deleted=0)

第一个表有 5913 行,第二个有 144992 行。

视图非常快,它会在 0.0011 秒内在 phpMyAdmin 中加载 20 个结果,但只要我在其上请求 GROUP BY(我需要它使用 SUM() 进行统计)es:

SELECT * FROM movements_items_view GROUP BY itemId LIMIT 0,20

时间跳到 0.2 秒或更多,它会导致“使用 where;使用临时;使用文件排序”在移动连接上。 任何帮助表示赞赏,谢谢。

编辑:

我还通过 phpMyAdmin 运行此查询以尝试不使用视图:

SELECT movements.movementId, movements.movementType, movements_items.qty 
    FROM movements_items
    JOIN movements ON movements.movementId=movements_items.movementId
    GROUP BY itemId LIMIT 0,20

而且性能是一样的。

编辑。这是解释

id  select_type     table               type    possible_keys                    key            key_len     ref                        rows     Extra   
1   SIMPLE          movements           index   PRIMARY,movementid               movement_type  1           NULL                       5913     Using index; Using temporary; Using filesort
1   SIMPLE          movements_items     ref     movementId,itemId,movementId_2   movementId_2   3           movements.movementId       12       Using index

【问题讨论】:

视图的 select 语句是否与添加的 group by 一起运行? 您从带有 group by 的视图中选择确实会读取所有记录;这似乎无法与您在 phpmyadmin 中返回 20 个结果的操作相提并论。 @ysth GROUP BY 查询也在 phpMyAdmin 中运行,因此需要 0.2 秒或更长时间才能获得 20 个结果。我正在编辑问题,我的错误。谢谢。 mysql 中的视图访问其底层索引的能力极为有限。因此,在我看来,它们毫无意义 @Strawberry 我理解,但它们让我节省了大量的 PHP 编码。我还尝试在不通过视图的情况下运行“本机”查询,并且性能是相同的。我可以做些什么来使用更好的索引或避免使用 GROUP BY? 【参考方案1】:

把它翻过来。看看这是否有效:

SELECT  movementId, m.movementType, mi.qty
    FROM
        ( SELECT  movementId, qty
            FROM  movements_items
            GROUP BY  itemId
            ORDER BY  itemId
            LIMIT  20 
        ) AS mi
    JOIN  movements AS m  USING(movementId)

诀窍是尽快完成LIMIT。最初的方式是将所有数据都拖走,而不仅仅是 20 行。

movements_items 中,是否没有“唯一”列或列组合?如果是这样,请将其设为PRIMARY KEY

movement 中,KEY movementId (movementId,deleted) 是多余的,应该删除。

movement_items 中,KEY movementId (movementId) 是多余的,应该删除。

【讨论】:

以上是关于mysql GROUP BY 真的慢上一个视图的主要内容,如果未能解决你的问题,请参考以下文章

带有 GROUP BY 的这个 MySQL 视图的 MS 版本?

使用 LEFT JOIN 的 MySQL 视图中的问题... GROUP BY

09_MySQL笔记-组函数-GROUP BY-LIMIT-多表连接查询-子查询-UNION-索引-视图-存储过程

mysql group by,两个条件,限制1

mysql group by,两个条件,限制1

sql:用group by分组后,每组随意取一个记录?