【问题标题】:Transparently compress attributes before storing in database in Rails在 Rails 中存储到数据库之前透明地压缩属性
【发布时间】:2012-02-11 18:39:47
【问题描述】:

我的一个模型有一个巨大的文本列,我想在将其存储到数据库之前对其进行压缩(不是为了节省磁盘空间,而是因为我不想通过网络发送未压缩的字段我的数据库服务器到我的应用服务器)

如果相关,我的数据库是 postgresql

这是我尝试编写的扩展,但由于某种原因,这在生产中不起作用(实际存储在数据库中的数据看起来像十六进制(例如“34bee1c2d099ba21da3ac533d5f99cda2654feb73985430df39c5ffd8fbf9d9ff3aa9392d5a5”而不是 Zlib 输出(例如“A\xEB\x \xF2Oy=\x9C\x7F5\xE9\xC44\x01M\")。不知道发生了什么

module HasCompressedAttributes
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def has_compressed_attributes(*fields)
      fields.each do |field|
        define_method(:"#{field}=") do |uncompressed|
          write_attribute(:"#{field}", Zlib::Deflate.deflate(uncompressed))
        end

        define_method(:"#{field}") do
          Zlib::Inflate.inflate(read_attribute(:"#{field}")) rescue nil
        end
      end
    end
  end
end

ActiveRecord::Base.class_eval{ include HasCompressedAttributes }

这里有更好的方法吗?也许是现有的宝石?

【问题讨论】:

    标签: ruby-on-rails database postgresql compression


    【解决方案1】:

    PostgreSQL 最新版本中bytea 的默认编码方式为"hex"

    “十六进制”格式将二进制数据编码为每个字节 2 个十六进制数字,最重要的半字节在前。整个字符串前面是序列 \x(以区别于转义格式)。

    所以您在数据库中看到的34bee1c2d099ba21da3ac... 只是十六进制编码的二进制数据。如果您使用bytea 列(即创建列时的t.binary)而不是textvarchar(即t.textt.string),AR 应该为您编码和解码这些内容.如果您要将二进制数据存储在数据库中,则必须使用t.binary,这样您就无法将这种魔力完全隐藏在模块中,还必须正确设置架构。

    【讨论】:

    • 我正在使用 bytea 列,但编码仍然错误(我在 Prod 和 Dev 中使用完全相同的数据库,它在 Dev 中有效但在 Prod 中无效,奇怪的是)
    • @Horace:你们在开发和生产中有不同的 PostgreSQL 版本吗?
    • @Horace:差别还不够,bytea_output 设置是否相同?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 2010-12-16
    • 1970-01-01
    • 2014-01-13
    • 2021-04-24
    • 1970-01-01
    相关资源
    最近更新 更多