Skip to content

Instantly share code, notes, and snippets.

@raggi
Created March 16, 2012 00:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save raggi/2047974 to your computer and use it in GitHub Desktop.
Save raggi/2047974 to your computer and use it in GitHub Desktop.
Mysql2 Column Cache for Rails 3.0.12
# = MONKEY PATCH: Memoize Mysql2 Columns
#
# Reduces SHOW FIELDS selects in production to essentially 0 calls.
#
# == Reason:
#
# * We have some pages that are (with rails 3.0.12) generating nearly 1200 SHOW
# FIELDS sql statements.
# * These come from ActiveRecord::Associations during complex join semantics.
# * Esentially, through some relations, Arel::Table instances don't have
# pre-cached column data, or access to the related AR::Base instance.
# * We have at least some routes that hit this many times.
#
# == Notes:
#
# * You cannot observe these SHOW FIELDS through the rails logs. They were
# observed using strace(1) on production systems, and noted due to the volume
# of calls.
# * This seems to occur on some quite heavily abstracted code (cross-engine
# code), and may not happen in "more normal" parts of the app.
# * The performance profile when running with a mysql server on localhost on an
# SSD will be far less drastic than against EBS on a different EC2 host,
# especially when a lot of calls are generated.
#
# == Caveats:
#
# * This is enabled for both production and test environments in order that we
# catch any issues that might arise from it.
# * It is disabled for development because the Mysql2Adapter will not be
# reloaded between model loads, which means new columns won't be found. It
# could also lead to other confusion for dev mode.
#
# == Original backtrace:
#
# N.B. Abbreviated:
#
# gems/arel-2.0.10/lib/arel/table.rb:97:in `columns'
# gems/arel-2.0.10/lib/arel/table.rb:104:in `[]'
# gems/activerecord-3.0.10/lib/active_record/associations.rb:2204:in `association_join'
# gems/activerecord-3.0.10/lib/active_record/relation/query_methods.rb:256:in `build_joins'
# gems/activerecord-3.0.10/lib/active_record/relation/query_methods.rb:254:in `each'
# gems/activerecord-3.0.10/lib/active_record/relation/query_methods.rb:254:in `build_joins'
# gems/activerecord-3.0.10/lib/active_record/relation/query_methods.rb:176:in `build_arel'
# gems/activerecord-3.0.10/lib/active_record/relation/query_methods.rb:149:in `arel'
# gems/activerecord-3.0.10/lib/active_record/relation.rb:321:in `to_sql'
# gems/activerecord-3.0.10/lib/active_record/relation/calculations.rb:207:in `execute_simple_calculation'
# gems/activerecord-3.0.10/lib/active_record/relation/calculations.rb:182:in `perform_calculation'
# gems/activerecord-3.0.10/lib/active_record/relation/calculations.rb:152:in `calculate'
# gems/activerecord-3.0.10/lib/active_record/relation/calculations.rb:58:in `count'
# gems/activerecord-3.0.10/lib/active_record/relation.rb:92:in `empty?'
# gems/activerecord-3.0.10/lib/active_record/relation.rb:100:in `any?'
# app/models/item.rb:158:in `votable_by?'
# ruby/1.8/delegate.rb:140:in `__send__'
# ruby/1.8/delegate.rb:140:in `votable_by?'
# ruby/1.8/delegate.rb:140:in `__send__'
# ruby/1.8/delegate.rb:140:in `votable_by?'
# app/liquid/gallery/drops/entry_drop.rb:47:in `_unmemoized_completed'
#
# == Original strace counts:
#
# ~ % grep 'SHOW FIELDS' request.txt| wc -l
# 1188
# ~ % grep 'SHOW FIELDS' request.txt| sort | uniq| wc -l
# 5
#
# == Additional Notes:
#
# * Some of this code changes by Rails 3.2, semantics may also.
# * It is possible that AR::Association is patchable, certainly at least one
# call to Arel::Table.new does not pass a :columns option that could be
# populated from objects in the scope.
# * It is also conceivable that this could be a reasonable configurable option
# for rails itself, something like +config.cache_sql_adapter_columns+.
#
if Rails.application.config.cache_classes
class ActiveRecord::ConnectionAdapters::Mysql2Adapter
extend ActiveSupport::Memoizable
memoize :columns
end
end
@mehagar
Copy link

mehagar commented Jun 15, 2020

Is this still needed for Rails 4.2 and later?

@raggi
Copy link
Author

raggi commented Jun 15, 2020

No idea, sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment