AWK与MySQL进行数据聚合

时间:2013-10-18 21:36:36

标签: mysql database performance awk

在试图弄清楚AWK或MySQL是否更有效地处理日志文件和返回聚合统计数据时,我注意到以下对我没有意义的行为:

为了测试这个,我使用了一个包含4列和大约9百万条记录的文件。我使用的是同一台服务器,这是一台带有SSD和1GB内存的VPS。

column1是一个包含大约10个唯一值的列,所有列组合的唯一值总数约为4k。

在MySQL中,我使用一个定义为表(column1,column2,column3,column4)的表,没有索引。

数据格式:

    column1,column2,column3,column4
    column1,column2,column3,column4

AWK脚本:

BEGIN {
    FS = ",";
    time = systime();
}  {
    array[$1]++;  #first test
    #array[$1 "," $2 "," $3 "," $4]++; #second test
}
} END {
    for (value in array) {
            print "array[" value "]=" array[value];
    }
}

MySQL查询:

Query 1: SELECT column1, count(*) FROM log_test GROUP BY column1;

Query 2: SELECT column1, column2, column3, column4, count(*) 
FROM log_test GROUP BY column1, column2, column3, column4;

AWK比预期的要慢。但是,当我运行第一个以10行返回聚合数据的测试时,MySQL需要大约7秒才能完成,而AWK需要大约22秒。

我知道awk逐行读取并处理数据,所以我希望当我运行第二次测试时,输出为4k行,AWK应该与第一次测试时间大致相同因为它仍然具有相同数量的行来读取它并没有做更多的处理。然而,AWK大约需要90秒,但只使用.1%MEM,而MySQL需要大约45秒并使用3%MEM。

  1. 为什么AWK在测试2中花费的时间比测试1要长得多,因为它实际上是在读同一个文件?
  2. 为什么AWK不使用更多内存并且将其值存储在内存中的硬盘副本上?
  3. 为什么MySQL在基本上必须逐行读取表格时要快得多?
  4. 是否有更有效的替代方法来汇总这些数据?

2 个答案:

答案 0 :(得分:0)

Awk必须在第二种情况下存储所有元组(并且处理更大的关联映射)。要验证这一点,请尝试2和3场计数的中间步骤

至于内存使用情况,你能看一下进程使用的确切字节数吗?强制awk在最后睡眠并测量两种情况下的内存使用情况(以字节为单位),你会看到差异

MySQL以比打印文本更有效的方式存储数值数据。更重要的是,它可能以预先解析的形式存储数据,而awk必须在每一行上执行昂贵的记录和字段拆分(您没有显示MySQL设置,但如果您使用了char(10)或其他固定的宽度字段MySQL不必重新处理数据)。

最有效的方法是预先排序或应用在更新时维护的索引,尽管它是以每次插入时间为代价的。或者,如果列很小且具有已知宽度,则可以编写自己的C实用程序,以利用这些假设(文件只是一组结构)

答案 1 :(得分:0)

在这两种情况下都需要进行现场拆分;你是对的,处理上的差异可以忽略不计。

但是,您需要考虑Awk如何实现关联数组的方法。为了增加给定的数组条目,它需要构造用作索引的字符串,然后在可能的索引列表中找到该条目。

我从问题陈述中推断出:

阵列[$ 1] ++

输入数据有10个不同的值,每个$ 1,每个值小于20个字符(如MYSQL表规范所示)。构造索引需要输入记录中的20个字符的副本。对于9百万输入记录中的每一个,只需要将最多10个字符串(每个少于20个字符串)与第一个字段进行比较,以确定要增加哪个“数组”条目。

但在以下情况下:

数组[$ 1“,”$ 2“,”$ 3“,”$ 4] ++

我们需要将最多80个字符从输入记录复制到组装索引的临时存储器中。在第一种情况下,我们只需要复制20个字符。

您说输出将有4000多行,这意味着在900万条记录的末尾,每个潜在的增量必须搜索并比较最多4000个80个字符串。

我不知道awk用于索引/散列关联数组索引的方法的详细信息(我希望它能以某种方式比直接搜索/比较迭代更有效),但你可以看到搜索10列表与4000列表可以产生影响。

您还会注意到输入字段的长度也会影响AWK处理。如果一个字段是5个字符而不是20个字符,那么复制该字段需要4倍的时间。

最后,请注意,在将AWK与MYSQL进行比较时,还必须考虑将数据加载到MYSQL数据库所需的时间。如果无论是使用AWK还是MYSQL来汇总输出,都会加载数据,那么使用MYSQL进行聚合可能会更好。

但是如果你只需要将它加载到MYSQL数据库中以便可以聚合,那么这次必须添加到QUERY时间,我认为最终结果会更接近。