Postgresql / Python压缩带有大量冗余行的文本列

时间:2016-09-11 23:46:59

标签: python algorithm postgresql compression

注意:

  • 我们正在使用Amazon RDS,所以我们可以使用的PostgreSQL扩展数量非常有限。
  • 我在RDS上说过PostgreSQL,因为1)我们必须使用AWS,2)我们想要最安全的数据完整性解决方案,花费最少的维护时间。 (如果其他服务更符合这些要求,我们愿意接受建议)
  • 我们有几TB的数据,因此空间效率很重要(但我们可以根据来源轻松进行分片)

我们希望将“logs”存储在一个表中,该表包含以下最小字段集(为了优化目的,可能会添加更多字段):

  • 时间
  • 水平
  • 消息

消息列具有以下特征    * 99%的时间非常短(<64个字符,但是例外情况它们可能很长&gt; 1024个字符)  *一些识别良好的消息可能占用消息数量的10%  *许多“近乎”重复的消息(即this system hs been up and running for X seconds
 *长尾的“独特”消息  *获取典型日期的消息并通过gzip运行它们很容易将大小除以15

现在我正在考虑两种可能的解决方案

压缩算法接受用户定义的“令牌”字典

我们的想法是拥有某种压缩算法,该算法可以根据我们识别的“重复文本”列表使用用户提供的“词典”并存储结果。由于我们的“应用程序”是唯一一个可以写入和读取的应用程序,因此我们可以“动态”解压缩

  • Pro :肯定会有一个非常好的压缩比
  • 缺点:我不知道在哪里搜索(LZ77?但我看不出来)

用于“完全”匹配预定义消息的字典表

  • LOGS_TABLE
  • 时间
  • 水平
  • dictionnary_id
  • 消息(可空)

_

  • DICTIONNARY_TABLE
  • dictionnary_id
  • 消息

_

  • 专业:我完全了解如何实施它,并且很容易“更新”
  • 缺点:不包括“近”匹配

对于这类问题,是否已有“最先进”的解决方案?

1 个答案:

答案 0 :(得分:1)

我终于选择了dictionnary表的想法

对于dictionnary_id我实际上使用了murmurhash 64 bits(并命名为id hash_message,这样我就可以先在python端预先计算它,因为它是非加密的,它是&#39;非常适合调用,对于python来说,它是mmh3模块的纯C实现。

我预装了dictionnary表,其中包含我从#34;典型的一天&#34;中获得的507百万条消息中的500k最常见(和重复)的日志。的日志。 然后我加载了执行以下INSERT请求的数据:

        INSERT INTO my_logs (
            service_id,
            creation_date,
            level,
            hash_message,
            message
        )
        SELECT
            %(hash_robot)s,
            %(creation_date)s,
            %(hash_message)s,
            NULLIF (
                %(message)s,
                min(message)
            )
        FROM dictionnary
        WHERE hash_message = %(hash_message)s;

通过这样做,如果message已经存在,则自动插入,并且只有在我的日志表中插入实际文本(如果它不存在于字典中)。

我的日志表的message列使用的平均值只有3个字节!这意味着大多数情况下消息表为空,虽然在我的dictionnary中添加更多日志是不值得的(并且从bigint为我的service_id切换到int实际上是一个更好的主意)