我想使用此查询在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毫秒!
这让我感到困惑,因为我认为应该{strong>之后使用GROUP BY
语句。
因此,我尝试一个不同的查询,以迫使mariadb仅将WHERE
应用于200行的子集中:
GROUP BY
问题仍然存在,第二季度给我的行为与第一季度完全相同。...
很有趣,第三季度可以正常工作并将执行时间从9s减少到100ms:
SELECT count(item_group_id)
FROM (SELECT * FROM item WHERE created > [-1 DAY]) t
GROUP BY item_group_id
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
到底要如何使mariadb的行为有所不同?谁能解释一下?
欢呼!
编辑:LIMIT
。
SHOW CREATE TABLE
答案 0 :(得分:0)
created
上没有索引,因此无法优化WHERE
子句,因此进行了全表扫描。添加此内容:
INDEX(created, item_group_id)
一旦表变得大于innodb_buffer_pool_size
,UUID就会严重影响性能。这是由于UUID的严重随机性,导致缓存无用,并且查询严重依赖于I / O。
更多
EXPLAIN
中的“行”数字不一定正确,有时甚至不接近。让我们进一步研究它。对查询的每个变体执行以下操作:
FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';
这将提供实际个计数,显示被触摸了多少行。通常,这是比较两个竞争查询的好指标。
真正的问题是UUID的随机性。
innodb_buffer_pool_size
更改为600M
。您所拥有的可能正在损坏磁盘。仅此一项,就可以将时间从9秒减少到1。utf8
对于十六进制字符串不是必需的。BINARY(16)
(16字节),从而缩小数据和索引的大小。这是减少I / O的另一种方法。更多:http://mysql.rjweb.org/doc.php/uuid