Class: Sequel::Postgres::StatementCache::StatementCache
- Includes:
- Enumerable
- Defined in:
- lib/sequel/extensions/pg_statement_cache.rb
Overview
The backbone of the block, a modified LRU (least recently used) cache mapping SQL query strings to Statement objects.
Instance Method Summary collapse
-
#clear ⇒ Object
Completely clear the statement cache, deallocating on the server side all statements that have been prepared.
-
#each(&block) ⇒ Object
Yield each SQL string and Statement instance in the cache to the block.
-
#fetch(sql) ⇒ Object
Get the related statement name from the cache.
-
#initialize(opts = {}, &block) ⇒ StatementCache
constructor
Set the options for the statement cache.
-
#size ⇒ Object
The current size of the statement cache.
Constructor Details
#initialize(opts = {}, &block) ⇒ StatementCache
Set the options for the statement cache. These are generally set at the database level using the :statement_cache_opts Database option.
- :max_size
-
The maximum size (high water mark) for the cache. If an entry is added when the current size of the cache is equal to the maximum size, the cache is cleaned up to reduce the number of entries to the :min_size. Defaults to 1000.
- :min_size
-
The minimum size (low water mark) for the cache. On cleanup, the size of the cache is reduced to this number. Note that there could be fewer than this number of entries in the cache. Defaults to :max_size/2.
- :prepare_after
-
The number of executions to wait for before preparing
the query server-side. If set to 1, prepares all executed
queries server-side. If set to 5, does not attempt to
prepare the query until the 5th execution. Defaults to 2.
- :sorter
-
A callable object that takes two arguments, the current time and the related Statement instance, and should return some Comparable (usually a numeric) such that the lowest values returned are the first to be removed when it comes time to clean the pool. The default is basically:
lambda{|t, stmt| (stmt.last_seen - t)/stmt.num_executes}
so that it doesn’t remove statements that have been executed many times just because many less-frequently executed statements have been executed recently.
The block passed is called with the Statement object’s name, only for statements that have been prepared, and should be used to deallocate the statements.
107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/sequel/extensions/pg_statement_cache.rb', line 107 def initialize(opts={}, &block) @cleanup_proc = block @prepare_after = opts.fetch(:prepare_after, 2) @max_size = opts.fetch(:max_size, 1000) @min_size = opts.fetch(:min_size, @max_size/2) @sorter = opts.fetch(:sorter){method(:default_sorter)} @ids = (1..@max_size).to_a.reverse @hash = {} # # We add one so that when we clean the cache, the entry # about to be added brings us to the min_size. @size_diff = @max_size - @min_size + 1 end |
Instance Method Details
#clear ⇒ Object
Completely clear the statement cache, deallocating on the server side all statements that have been prepared.
123 124 125 |
# File 'lib/sequel/extensions/pg_statement_cache.rb', line 123 def clear @hash.keys.each{|k| remove(k)} end |
#each(&block) ⇒ Object
Yield each SQL string and Statement instance in the cache to the block.
129 130 131 |
# File 'lib/sequel/extensions/pg_statement_cache.rb', line 129 def each(&block) @hash.each(&block) end |
#fetch(sql) ⇒ Object
Get the related statement name from the cache. If the entry is already in the cache, just bump it’s last seen time and the number of executions. Otherwise, add it to the cache. If the cache is already full, clean it up before adding it.
If the num of executions has passed the threshhold, yield the statement name to the block, which should be used to prepare the statement on the server side.
This method should return the prepared statment name if the statement has been prepared, and nil if the query has not been prepared and the statement should be executed normally.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/sequel/extensions/pg_statement_cache.rb', line 147 def fetch(sql) unless stmt = @hash[sql] # Get the next id from the id pool. unless id = @ids.pop # No id left, cache must be full, so cleanup and then # get the next id from the id pool. cleanup id = @ids.pop end @hash[sql] = stmt = Statement.new(id) end stmt.last_seen = Time.now stmt.num_executes += 1 if stmt.num_executes >= @prepare_after if stmt.num_executes == @prepare_after begin yield(stmt.name) rescue PGError # An error occurred while preparing the statement, # execute it normally (which will probably raise # the error again elsewhere), but decrement the # number of executions so we don't think we've # prepared the statement when we haven't. stmt.num_executes -= 1 return nil end end stmt.name end end |
#size ⇒ Object
The current size of the statement cache.
181 182 183 |
# File 'lib/sequel/extensions/pg_statement_cache.rb', line 181 def size @hash.length end |