【发布时间】:2018-12-26 02:59:17
【问题描述】:
我想在 mariadb 上使用此查询对一个相当大的表的子集进行分组:
第一季度
SELECT count(item_group_id)
FROM item
WHERE created > [-1 DAY]
GROUP BY item_group_id
created > [-1 DAY] 的子集只有大约 200 行。整组表item 有超过一百万 行。
查询耗时 9 秒!
如果没有GROUPY BY,查询需要 40 毫秒!
这让我很困惑,因为我认为应该在 在WHERE 语句之后应用 GROUP BY 语句。
所以我尝试了一个不同的查询,强制 mariadb 仅在 200 行的子集上应用 GROUP BY:
第二季度
SELECT count(item_group_id)
FROM (SELECT * FROM item WHERE created > [-1 DAY]) t
GROUP BY item_group_id
不过,Q2 给了我与 Q1 完全相同的行为......
很有趣,Q3 成功了,并将执行时间从 9 秒缩短到了 100 毫秒:
第三季度
SELECT count(item_group_id)
FROM (SELECT * FROM item WHERE created > [-1 DAY] LIMIT 100000000) t
GROUP BY item_group_id
解释第二季度
+----+-------------+-------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | item | index | NULL | PRIMARY | 108 | NULL | 643167 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+--------+-------------+
解释第三季度
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 643207 | Using temporary; Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
| 2 | DERIVED | item | ALL | NULL | NULL | NULL | NULL | 643207 | |
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
使用LIMIT [large number] 完全符合我的要求并创建了临时表之前 应用GROUP BY
LIMIT 究竟做了什么让 mariadb 表现不同?谁能解释一下?
干杯!
编辑:SHOW CREATE TABLE。
CREATE TABLE `item` (
`id` char(36) COLLATE utf8_unicode_ci NOT NULL COMMENT '(DC2Type:uuid)',
`item_group_id` char(36) COLLATE utf8_unicode_ci NOT NULL COMMENT '(DC2Type:uuid)',
`content_id` char(36) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '(DC2Type:uuid)',
`section_id` char(36) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '(DC2Type:uuid)',
`person_id` char(36) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '(DC2Type:uuid)',
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_D4707EBD57B8F0DE` (`item_group_id`),
KEY `IDX_D4707EBDD07ECCB6` (`content_id`),
KEY `IDX_D4707EBDF639F774` (`section_id`),
KEY `IDX_D4707EBD9395C3F3` (`person_id`),
CONSTRAINT `FK_D4707EBD57B8F0DE` FOREIGN KEY (`item_group_id`) REFERENCES `item_group` (`id`),
CONSTRAINT `FK_D4707EBD9395C3F3` FOREIGN KEY (`person_id`) REFERENCES `pseron` (`id`) ON DELETE SET NULL,
CONSTRAINT `FK_D4707EBDD07ECCB6` FOREIGN KEY (`content_id`) REFERENCES `content` (`id`) ON DELETE SET NULL,
CONSTRAINT `FK_D4707EBDF639F774` FOREIGN KEY (`section_id`) REFERENCES `section` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
【问题讨论】:
-
请提供
SHOW CREATE TABLE。我们需要查看索引、引擎和其他内容。 -
@RickJames 我已经添加了节目创建。谢谢。
-
生成临时表的成本很高;分类成本很高;可能是缓存导致更复杂的查询更快。运行两种口味两次;报告时间。 (缓存是速度差异的一个重要因素。)
-
CHAR(36)-- 闻起来像 UUID;他们是吗?表有多大 (GB)?innodb_buffer_pool_size的设置是什么? -
是的,Uuid。此外,innodb_buffer_pool_size : 134217728。该表只有大约 230mb(650 000 行)。
标签: mysql sql performance mariadb