diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2011-09-06 16:47:34 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2011-09-06 16:47:34 -0700 |
commit | 54b7e783ef202d022a57dcdd54f7edf021c1df78 (patch) | |
tree | b422ab3d93685c806f3b1405ffdf410c9d5b8dd4 /activerecord/lib | |
parent | a4fa6eab396e703eb70b70ed708220a6405f2899 (diff) | |
download | rails-54b7e783ef202d022a57dcdd54f7edf021c1df78.tar.gz rails-54b7e783ef202d022a57dcdd54f7edf021c1df78.tar.bz2 rails-54b7e783ef202d022a57dcdd54f7edf021c1df78.zip |
Database adapters use a statement pool.
Database adapters use a statement pool for limiting the number of open
prepared statments on the database. The limit defaults to 1000, but can
be adjusted in your database config by changing 'statement_limit'.
Diffstat (limited to 'activerecord/lib')
3 files changed, 46 insertions, 8 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 8ecb3cefde..73e3afe1d5 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -120,7 +120,8 @@ module ActiveRecord def initialize(connection, logger, connection_options, config) super - @statements = StatementPool.new(@connection) + @statements = StatementPool.new(@connection, + config.fetch(:statement_limit) { 1000 }) @client_encoding = nil connect end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ba4a6c7a78..a09bf9c73f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,5 +1,6 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_support/core_ext/object/blank' +require 'active_record/connection_adapters/statement_pool' # Make sure we're using pg high enough for PGResult#values gem 'pg', '~> 0.11' @@ -246,6 +247,43 @@ module ActiveRecord true end + class StatementPool < ConnectionAdapters::StatementPool + def initialize(connection, max) + super + @counter = 0 + @cache = {} + end + + def each(&block); @cache.each(&block); end + def key?(key); @cache.key?(key); end + def [](key); @cache[key]; end + def length; @cache.length; end + + def next_key + "a#{@counter + 1}" + end + + def []=(sql, key) + while @max <= @cache.size + dealloc(@cache.shift.last) + end + @counter += 1 + @cache[sql] = key + end + + def clear + @cache.each_value do |stmt_key| + dealloc stmt_key + end + @cache.clear + end + + private + def dealloc(key) + @connection.query "DEALLOCATE #{key}" + end + end + # Initializes and connects a PostgreSQL adapter. def initialize(connection, logger, connection_parameters, config) super(connection, logger) @@ -254,9 +292,10 @@ module ActiveRecord # @local_tz is initialized as nil to avoid warnings when connect tries to use it @local_tz = nil @table_alias_length = nil - @statements = {} connect + @statements = StatementPool.new @connection, + config.fetch(:statement_limit) { 1000 } if postgresql_version < 80200 raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!" @@ -271,9 +310,6 @@ module ActiveRecord # Clears the prepared statements cache. def clear_cache! - @statements.each_value do |value| - @connection.query "DEALLOCATE #{value}" - end @statements.clear end @@ -996,7 +1032,7 @@ module ActiveRecord def exec_cache(sql, binds) unless @statements.key? sql - nextkey = "a#{@statements.length + 1}" + nextkey = @statements.next_key @connection.prepare nextkey, sql @statements[sql] = nextkey end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index a4e21b714b..7c7e762c19 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -50,7 +50,7 @@ module ActiveRecord end class StatementPool < ConnectionAdapters::StatementPool - def initialize(connection, max = 1000) + def initialize(connection, max) super @cache = {} end @@ -82,7 +82,8 @@ module ActiveRecord def initialize(connection, logger, config) super(connection, logger) - @statements = StatementPool.new(@connection) + @statements = StatementPool.new(@connection, + config.fetch(:statement_limit) { 1000 }) @config = config end |