mysql GROUP BY 就一个 View 确实很慢

标签 mysql optimization indexing view

我有这些 table 。

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`);

这个 View 称为“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 行。

该 View 非常快,它在 0.0011s 内加载了 PhpMyAdmin 中的 20 个结果,但是当我要求对其进行 GROUP BY 时(我需要它使用 SUM() 进行统计)es:

SELECT * FROM movements_items_view GROUP BY itemId LIMIT 0,20

时间跳到 0.2 秒或更长,并导致移动连接时出现“Using where;Using tempor;Using filesort”。 感谢任何帮助,谢谢。

编辑:

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

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  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中,没有列或列组合是“唯一的”吗?如果是这样,请将其设为主键

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

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

关于mysql GROUP BY 就一个 View 确实很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59340374/

相关文章:

mysql - 调整 MySQL 以在开发过程中快速创建列/索引

python - 使用自定义函数创建 n*n DataFrame

sql-server - 过滤索引与普通非聚集索引

sql - 为数据库中的所有表创建索引?

jquery - jquery 单独的 dom 元素上的重复索引

mysql - 显示时更改行中的 Mysql 值

mysql - 用于在 MySQL 中验证 URL 的正则表达式

linux - 有没有可以在Linux上运行的好的并行混合整数编程优化器?

php - 严格标准 : Only variables should be passed by reference PHP Shopping Cart

PHP层次结构/画廊系统