5

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

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

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

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

数据格式:

    第 1 列,第 2 列,第 3 列,第 4 列
    第 1 列,第 2 列,第 3 列,第 4 列

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 比 MySQL 慢。但是,当我运行第一个返回包含 10 行的聚合数据的测试时,MySQL 大约需要 7 秒才能完成,而 AWK 大约需要 22 秒。

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

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

3 回答 3

0

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

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

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

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

于 2013-10-18T21:49:07.427 回答
0

在这两种情况下,都需要进行字段拆分;您说得对,处理上的差异可以忽略不计。

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

我从问题陈述中推断,在以下情况下:

数组[$1]++

输入数据对于 $1 有 10 个不同的值,每个值少于 20 个字符(如 MYSQL 表规范所示)。构建索引需要从输入记录中复制 20 个字符。对于 900 万个输入记录中的每一个,最多只有 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时间,我认为最终结果会更接近。

于 2013-11-05T18:43:44.633 回答
0

如果您认为大型文本文件可以按 8:1 压缩,并且 SQL 不会将数据存储为 ascii 文本(它使用压缩方法)并且解压缩比从磁盘读取要快得多(您会在低处理器活动中看到这一点)。

如果 sql 能够直接搜索压缩数据,则涉及的工作要少得多。索引和其他前期工作由 sql 完成,以使 sql 中的搜索也更快。

于 2022-01-16T15:15:02.413 回答