mariadb小组对小子集进行缓慢讨论

时间:2018-07-18 09:01:04

标签: mysql sql performance mariadb

我想使用此查询在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:

Q3

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

1 个答案:

答案 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的随机性。

  • 假设您至少有4GB的RAM,请将innodb_buffer_pool_size更改为600M。您所拥有的可能正在损坏磁盘。仅此一项,就可以将时间从9秒减少到1。
  • 考虑使用UUID以外的其他内容。
  • utf8对于十六进制字符串不是必需的。
  • 可以将UUID从当前大小36(或由于utf8而可能是108)缩小到BINARY(16)(16字节),从而缩小数据和索引的大小。这是减少I / O的另一种方法。更多:http://mysql.rjweb.org/doc.php/uuid