Group By MariaDB 非常慢

Group By MariaDB very slow

我在 Linux 下使用 MariDB 10.1.18。

我有一个简单的 table (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

出于性能目的,使用的引擎是 MEMORY

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

我认为如果我使用松散索引搜索就可以解决这个问题。不幸的是,这似乎在 MariaDB 中不起作用,因为它从未被使用过。 loosescan 设置为打开。

我试过了

SELECT MAX(a) FROM t GROUP BY a

我的数据库需要 1.1 秒。

问题是,我怎样才能让这个 select 变得非常快?比如0.05秒。

谢谢!

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

SELECT MAX(a) FROM t GROUP BY a

可以重写为

SELECT a FROM t GROUP BY a

SELECT DISTINCT a FROM t

需要 "zero" 时间。

您的第一个查询将 return 每组的第一行。假设您没有 full-table-index - 它将是按 id 排序的第一行。所以相当于"Find the oldest record per group",可以重写为

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

并且也在"no time"执行。

但是像

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

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

我在具有 370 万行和 30 个组的 InnoDB table 上测试了类似的查询。

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

  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) 为计划器提供足够的灵活性来处理任何类型的查询。索引必须是 BTREE。

对 500 万行的非常复杂的查询 table 现在大约需要 0.35 秒。