Skip to content
This repository
Browse code

Improve performance on :include/:conditions/:limit queries by selecti…

…vely joining in the pre-query. Closes #9560 [dasil003]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8977 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 4ca170fcea17ca0cd52677c39e865a0934ecd7d3 1 parent 51b6619
Michael Koziarski NZKoz authored
2  activerecord/CHANGELOG
... ... @@ -1,5 +1,7 @@
1 1 *SVN*
2 2
  3 +* Improve performance on :include/:conditions/:limit queries by selectively joining in the pre-query. #9560 [dasil003]
  4 +
3 5 * Perf fix: Avoid the use of named block arguments. Closes #11109 [adymo]
4 6
5 7 * PostgreSQL: support server versions 7.4 through 8.0 and the ruby-pg driver. #11127 [jdavis]
37 activerecord/lib/active_record/associations.rb
@@ -1388,7 +1388,13 @@ def select_limited_ids_list(options, join_dependency)
1388 1388
1389 1389 def construct_finder_sql_for_association_limiting(options, join_dependency)
1390 1390 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)
1392 1398 sql = "SELECT "
1393 1399 if is_distinct
1394 1400 sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", options[:order])
@@ -1398,7 +1404,7 @@ def construct_finder_sql_for_association_limiting(options, join_dependency)
1398 1404 sql << " FROM #{connection.quote_table_name table_name} "
1399 1405
1400 1406 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
1402 1408 add_joins!(sql, options, scope)
1403 1409 end
1404 1410
@@ -1416,8 +1422,7 @@ def construct_finder_sql_for_association_limiting(options, join_dependency)
1416 1422 return sanitize_sql(sql)
1417 1423 end
1418 1424
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)
1421 1426 # look in both sets of conditions
1422 1427 conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond|
1423 1428 case cond
@@ -1426,17 +1431,29 @@ def include_eager_conditions?(options)
1426 1431 else all << cond
1427 1432 end
1428 1433 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|
1431 1448 condition_table_name != table_name
1432 1449 end
1433 1450 end
1434 1451
1435 1452 # 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|
1440 1457 order_table_name != table_name
1441 1458 end
1442 1459 end

0 comments on commit 4ca170f

Please sign in to comment.
Something went wrong with that request. Please try again.