PostgreSQL の Array を使うと ActiveRecord の初期化が重くなる場合がある事を学んだ
6259 ワード
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
Author And Source
この問題について(PostgreSQL の Array を使うと ActiveRecord の初期化が重くなる場合がある事を学んだ), 我々は、より多くの情報をここで見つけました https://qiita.com/koshigoe/items/6f9694ff5bbe49e3c505著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .