Group By MariaDB非常慢

时间:2016-11-04 11:23:04

标签: mysql performance group-by mariadb

我在Linux下使用MariDB 10.1.18。

我有一个简单的表(t),结构如下:

| id | a | b |  c |
------------------- 
|  1 | 3 | 7 | 10 |
|  2 | 4 | 6 | 9  |
|  3 | 2 | 7 | 11 |
|  4 | 3 | 5 | 10 |
|  5 | 4 | 8 | 12 |
|  6 | 2 | 9 | 6  |


id is primary key
a - has BTREE index
b - has HASH index
c - has HASH index

我假设主键自动编入索引。 我的查询很简单:

SELECT * FROM t GROUP BY a

出于性能目的,ENGINE USED为MEMORY

在500万行上,上述查询需要 1秒来完成并利用一个CPU的线程到100%。现在,第a列约有150个唯一值。

我认为如果我使用松散的索引搜索,这可以解决。不幸的是,这似乎在MariaDB中不起作用,因为它从未使用过。 loosescan将开启。

我试过了

SELECT MAX(a) FROM t GROUP BY a

我的数据库需要1.1秒。

问题是,我怎样才能让这个选择速度快?喜欢0.05秒。

谢谢!

2 个答案:

答案 0 :(得分:0)

这取决于你真正想要的东西。你的两个查询都没有多大意义。

SELECT MAX(a) FROM t GROUP BY a

可以改写为

SELECT a FROM t GROUP BY a

SELECT DISTINCT a FROM t

并且需要“零”时间。

您的第一个查询将返回每个组的第一行。假设你没有全表索引 - 它将是按id排序的第一行。因此它相当于“查找每组最早的记录”,并且可以重写为

select t.*
from (
    select min(id) as id
    from t
    group by a
) m
join t using(id)

并且也在“没时间”执行。

但像

这样的查询
select count(id) as id
from t
group by a

会很慢。与SUM()AVG()相同,因为engin需要读取每一行。虽然MIN()MAX()每组只需要读取一行。

我在InnoDB表上测试了类似的查询,其中包含3.7 M行和30组。

答案 1 :(得分:0)

因此,经过大量的工作和测试,这是迄今为止最快的解决方案:

  1. 使用记忆引擎 - 它比存储在RAMDISK上的InnoDB快至少10倍

  2. 为每个" a"单独查询列元素而不是使用Group BY并将结果合并到PHP中 防爆。 SELECT id FROM t WHERE b IN(3,4,5)AND c IN(6,7,8)AND a = 1;

  3. 为每个列设置复合索引,如INDEX ON(a,b),INDEX ON(a,c),为计划者提供足够的灵活性以适应任何类型的查询。 INDEXES必须是BTREE。

  4. 5 mil行表上的一个非常复杂的查询现在大约需要0.35秒。