LoginSignup
3
3

More than 5 years have passed since last update.

PostgreSQL の Array を使うと ActiveRecord の初期化が重くなる場合がある事を学んだ

Posted at

Rails 4.2.6, Ruby 2.3.1, PostgreSQL 9.5.2 の話

1MBくらいの要素を追加したら(!?)、SELECT 後のインスタンス初期化で非常に待たされました。
試しにカラムの型を jsonb に変更してみたところ、多少はマシになりました。

ActiveRecord のコードを探ってみると、デフォルトでは Ruby で書かれたパーサによって PostgreSQL の Array を Ruby の Array にキャストしている事が分かりました。

lib/active_record/connection_adapters/postgresql/oid/array.rb
module ActiveRecord
  module ConnectionAdapters
    module PostgreSQL
      module OID # :nodoc:
        class Array < Type::Value # :nodoc:
          include Type::Mutable

          # Loads pg_array_parser if available. String parsing can be
          # performed quicker by a native extension, which will not create
          # a large amount of Ruby objects that will need to be garbage
          # collected. pg_array_parser has a C and Java extension
          begin
            require 'pg_array_parser'
            include PgArrayParser
          rescue LoadError
            require 'active_record/connection_adapters/postgresql/array_parser'
            include PostgreSQL::ArrayParser
          end

ということで、PostgreSQL の Array を使う場合は DockYard/pg_array_parser を使っておくと良さそうです。
(DockYard/pg_array_parser のコードは読んでませんし、2013年でコミットは止まっている様です。)

一方その頃 Rails 5.0.0 は

pg が持っている機能を使っている様です。

lib/active_record/connection_adapters/postgresql/oid/array.rb
module ActiveRecord
  module ConnectionAdapters
    module PostgreSQL
      module OID # :nodoc:
        class Array < Type::Value # :nodoc:
          include Type::Helpers::Mutable

          attr_reader :subtype, :delimiter
          delegate :type, :user_input_in_time_zone, :limit, to: :subtype

          def initialize(subtype, delimiter = ',')
            @subtype = subtype
            @delimiter = delimiter

            @pg_encoder = PG::TextEncoder::Array.new name: "#{type}[]", delimiter: delimiter
            @pg_decoder = PG::TextDecoder::Array.new name: "#{type}[]", delimiter: delimiter
          end
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3