Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 8977

Show
Ignore:
Timestamp:
03/03/08 06:23:38 (1 year ago)
Author:
nzkoz
Message:

Improve performance on :include/:conditions/:limit queries by selectively joining in the pre-query. Closes #9560 [dasil003]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r8957 r8977  
    11*SVN* 
     2 
     3* Improve performance on :include/:conditions/:limit queries by selectively joining in the pre-query.  #9560 [dasil003] 
    24 
    35* Perf fix: Avoid the use of named block arguments.  Closes #11109 [adymo] 
  • trunk/activerecord/lib/active_record/associations.rb

    r8942 r8977  
    13891389        def construct_finder_sql_for_association_limiting(options, join_dependency) 
    13901390          scope       = scope(:find) 
    1391           is_distinct = !options[:joins].blank? || include_eager_conditions?(options) || include_eager_order?(options) 
     1391 
     1392          # Only join tables referenced in order or conditions since this is particularly slow on the pre-query. 
     1393          tables_from_conditions = conditions_tables(options) 
     1394          tables_from_order      = order_tables(options) 
     1395          all_tables             = tables_from_conditions + tables_from_order 
     1396 
     1397          is_distinct = !options[:joins].blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order) 
    13921398          sql = "SELECT " 
    13931399          if is_distinct 
     
    13991405 
    14001406          if is_distinct 
    1401             sql << join_dependency.join_associations.collect(&:association_join).join 
     1407            sql << join_dependency.join_associations.reject{ |ja| !all_tables.include?(ja.table_name) }.collect(&:association_join).join 
    14021408            add_joins!(sql, options, scope) 
    14031409          end 
     
    14171423        end 
    14181424 
    1419         # Checks if the conditions reference a table other than the current model table 
    1420         def include_eager_conditions?(options) 
     1425        def conditions_tables(options) 
    14211426          # look in both sets of conditions 
    14221427          conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond| 
     
    14271432            end 
    14281433          end 
    1429           return false unless conditions.any? 
    1430           conditions.join(' ').scan(/([\.\w]+).?\./).flatten.any? do |condition_table_name| 
     1434          conditions.join(' ').scan(/([\.\w]+).?\./).flatten 
     1435        end 
     1436 
     1437        def order_tables(options) 
     1438          order = options[:order] 
     1439          return [] unless order && order.is_a?(String) 
     1440          order.scan(/([\.\w]+).?\./).flatten 
     1441        end 
     1442 
     1443        # Checks if the conditions reference a table other than the current model table 
     1444        def include_eager_conditions?(options,tables = nil) 
     1445          tables = conditions_tables(options) 
     1446          return false unless tables.any? 
     1447          tables.any? do |condition_table_name| 
    14311448            condition_table_name != table_name 
    14321449          end 
     
    14341451 
    14351452        # Checks if the query order references a table other than the current model's table. 
    1436         def include_eager_order?(options
    1437           order = options[:order] 
    1438           return false unless order 
    1439           order.to_s.scan(/([\.\w]+).?\./).flatten.any? do |order_table_name| 
     1453        def include_eager_order?(options,tables = nil
     1454          tables = order_tables(options) 
     1455          return false unless tables.any? 
     1456          tables.any? do |order_table_name| 
    14401457            order_table_name != table_name 
    14411458          end