Skip to content

Commit b610333

Browse files
Improve performance of reading cache entries (#198)
* Query directly through the database connection This prevents the instantiation of active record objects We can't assume prepared statements are available, so we go through `Arel.sql` to construct the query, which will handle that part, depending on availablity.
1 parent f7c84d8 commit b610333

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

app/models/solid_cache/entry.rb

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ def read(key)
3333

3434
def read_multi(keys)
3535
without_query_cache do
36-
find_by_sql([select_sql(keys), *key_hashes_for(keys)]).pluck(:key, :value).to_h
36+
query = Arel.sql(select_sql(keys), *key_hashes_for(keys))
37+
38+
connection.select_all(query, "SolidCache::Entry Load").cast_values(attribute_types).to_h
3739
end
3840
end
3941

@@ -84,13 +86,24 @@ def upsert_unique_by
8486
connection.supports_insert_conflict_target? ? :key_hash : nil
8587
end
8688

89+
# This constructs and caches a SQL query for a given number of keys.
90+
#
91+
# The query is constructed with two bind parameters to generate an IN (...) condition,
92+
# which is then replaced with the correct amount based on the number of keys. The
93+
# parameters are filled later when executing the query. This is done through Active Record
94+
# to ensure the field and table names are properly quoted and escaped based on the used database adapter.
95+
96+
# For example: The query for 4 keys will be transformed from:
97+
# > SELECT "key", "value" FROM "solid_cache_entries" WHERE "key_hash" IN (1111, 2222)
98+
# into:
99+
# > SELECT "key", "value" FROM "solid_cache_entries" WHERE "key_hash" IN (?, ?, ?, ?)
87100
def select_sql(keys)
88-
@get_sql ||= {}
89-
@get_sql[keys.count] ||= \
90-
where(key_hash: [ "1111", "2222" ])
101+
@select_sql ||= {}
102+
@select_sql[keys.count] ||= \
103+
where(key_hash: [ 1111, 2222 ])
91104
.select(:key, :value)
92105
.to_sql
93-
.gsub("1111, 2222", (["?"] * keys.count).join(", "))
106+
.gsub("1111, 2222", Array.new(keys.count, "?").join(", "))
94107
end
95108

96109
def key_hash_for(key)

0 commit comments

Comments
 (0)