mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Improve performance on :include/:conditions/:limit queries by selectively joining in the pre-query. Closes #9560 [dasil003]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8977 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
51b6619d4e
commit
4ca170fcea
2 changed files with 29 additions and 10 deletions
|
@ -1,5 +1,7 @@
|
||||||
*SVN*
|
*SVN*
|
||||||
|
|
||||||
|
* Improve performance on :include/:conditions/:limit queries by selectively joining in the pre-query. #9560 [dasil003]
|
||||||
|
|
||||||
* Perf fix: Avoid the use of named block arguments. Closes #11109 [adymo]
|
* Perf fix: Avoid the use of named block arguments. Closes #11109 [adymo]
|
||||||
|
|
||||||
* PostgreSQL: support server versions 7.4 through 8.0 and the ruby-pg driver. #11127 [jdavis]
|
* PostgreSQL: support server versions 7.4 through 8.0 and the ruby-pg driver. #11127 [jdavis]
|
||||||
|
|
|
@ -1388,7 +1388,13 @@ module ActiveRecord
|
||||||
|
|
||||||
def construct_finder_sql_for_association_limiting(options, join_dependency)
|
def construct_finder_sql_for_association_limiting(options, join_dependency)
|
||||||
scope = scope(:find)
|
scope = scope(:find)
|
||||||
is_distinct = !options[:joins].blank? || include_eager_conditions?(options) || include_eager_order?(options)
|
|
||||||
|
# Only join tables referenced in order or conditions since this is particularly slow on the pre-query.
|
||||||
|
tables_from_conditions = conditions_tables(options)
|
||||||
|
tables_from_order = order_tables(options)
|
||||||
|
all_tables = tables_from_conditions + tables_from_order
|
||||||
|
|
||||||
|
is_distinct = !options[:joins].blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order)
|
||||||
sql = "SELECT "
|
sql = "SELECT "
|
||||||
if is_distinct
|
if is_distinct
|
||||||
sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", options[:order])
|
sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", options[:order])
|
||||||
|
@ -1398,7 +1404,7 @@ module ActiveRecord
|
||||||
sql << " FROM #{connection.quote_table_name table_name} "
|
sql << " FROM #{connection.quote_table_name table_name} "
|
||||||
|
|
||||||
if is_distinct
|
if is_distinct
|
||||||
sql << join_dependency.join_associations.collect(&:association_join).join
|
sql << join_dependency.join_associations.reject{ |ja| !all_tables.include?(ja.table_name) }.collect(&:association_join).join
|
||||||
add_joins!(sql, options, scope)
|
add_joins!(sql, options, scope)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1416,8 +1422,7 @@ module ActiveRecord
|
||||||
return sanitize_sql(sql)
|
return sanitize_sql(sql)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Checks if the conditions reference a table other than the current model table
|
def conditions_tables(options)
|
||||||
def include_eager_conditions?(options)
|
|
||||||
# look in both sets of conditions
|
# look in both sets of conditions
|
||||||
conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond|
|
conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond|
|
||||||
case cond
|
case cond
|
||||||
|
@ -1426,17 +1431,29 @@ module ActiveRecord
|
||||||
else all << cond
|
else all << cond
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false unless conditions.any?
|
conditions.join(' ').scan(/([\.\w]+).?\./).flatten
|
||||||
conditions.join(' ').scan(/([\.\w]+).?\./).flatten.any? do |condition_table_name|
|
end
|
||||||
|
|
||||||
|
def order_tables(options)
|
||||||
|
order = options[:order]
|
||||||
|
return [] unless order && order.is_a?(String)
|
||||||
|
order.scan(/([\.\w]+).?\./).flatten
|
||||||
|
end
|
||||||
|
|
||||||
|
# Checks if the conditions reference a table other than the current model table
|
||||||
|
def include_eager_conditions?(options,tables = nil)
|
||||||
|
tables = conditions_tables(options)
|
||||||
|
return false unless tables.any?
|
||||||
|
tables.any? do |condition_table_name|
|
||||||
condition_table_name != table_name
|
condition_table_name != table_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Checks if the query order references a table other than the current model's table.
|
# Checks if the query order references a table other than the current model's table.
|
||||||
def include_eager_order?(options)
|
def include_eager_order?(options,tables = nil)
|
||||||
order = options[:order]
|
tables = order_tables(options)
|
||||||
return false unless order
|
return false unless tables.any?
|
||||||
order.to_s.scan(/([\.\w]+).?\./).flatten.any? do |order_table_name|
|
tables.any? do |order_table_name|
|
||||||
order_table_name != table_name
|
order_table_name != table_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue