2009-01-04 8 views
2

Je fais un ActiveRecord trouver l'opération (via la bibliothèque « will_paginate ») comme ceci:Pourquoi ActiveRecord émet une requête distincte par jointure?

contacts = Contact.paginate(:all, 
    :conditions => conditions_specified, 
    :select => "DISTINCT contacts.*", 
    :joins => joins, 
    :include => [:addresses, :emails, :phone_numbers, {:addresses => :organization}], 
    :page => page, 
    :per_page => @@PAGE_SIZE, 
    :order => 'last_name, first_name, middle_name') 

Dans la console, je reçois la sortie ci-dessous. En définissant le paramètre include, j'attends que cela aboutisse à une seule requête. Mais dans la sortie, je vois beaucoup de requêtes. Par exemple, je suis surpris de voir la ligne ...

Address Load (2.5ms) SELECT `addresses`.* FROM `addresses` WHERE (`addresses`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) 

dans la sortie ci-dessous. (Je comprends que les SHOW FIELDS FROM requêtes sont mises en cache dans la production de sorte que n'est pas un problème. Il est tout Selects supplémentaire que j'essaie de comprendre.)

Processing ContactController#index (for 127.0.0.1 at 2009-01-03 21:21:18) [GET] 
    Session ID: d453897c2f67c29c9a68d3fbc7b94f7b 
    ContactSearch Columns (4.4ms) SHOW FIELDS FROM `contact_searches` 
    Contact Load (1.1ms) SELECT DISTINCT contacts.* FROM `contacts` WHERE (contacts.last_name LIKE '%n%') ORDER BY last_name, first_name, middle_name LIMIT 0, 35 
    Contact Columns (2.3ms) SHOW FIELDS FROM `contacts` 
    Address Load (2.5ms) SELECT `addresses`.* FROM `addresses` WHERE (`addresses`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) 
    Address Columns (2.7ms) SHOW FIELDS FROM `addresses` 
    Email Load (1.7ms) SELECT `emails`.* FROM `emails` WHERE (`emails`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) 
    Email Columns (1.8ms) SHOW FIELDS FROM `emails` 
    PhoneNumber Load (3.3ms) SELECT `phone_numbers`.* FROM `phone_numbers` WHERE (`phone_numbers`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) 
    PhoneNumber Columns (3.0ms) SHOW FIELDS FROM `phone_numbers` 
    Organization Columns (2.9ms) SHOW FIELDS FROM `organizations` 
    Organization Load (0.9ms) SELECT * FROM `organizations` WHERE (`organizations`.`id` IN (99,116,44,6,23,78,107,91,79,119,14,120,71,26,59,94,27,100,62,1,51,29,30,2,65,76,5)) 
Rendering template within layouts/main 
Rendering contact/index 
Rendered contact/_field_function_specifier (0.9ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_field_function_specifier (0.6ms) 
Rendered contact/_search_form (14.1ms) 
Rendered contact/_quick_view_contact_info (3.2ms) 
Rendered contact/_quick_view_contact_info (2.1ms) 
Rendered contact/_quick_view_contact_info (1.9ms) 
Rendered contact/_quick_view_contact_info (1.9ms) 
Rendered contact/_quick_view_contact_info (0.8ms) 
Rendered contact/_quick_view_contact_info (2.0ms) 
Rendered contact/_quick_view_contact_info (2.4ms) 
Rendered contact/_quick_view_contact_info (1.7ms) 
Rendered contact/_quick_view_contact_info (1.4ms) 
Rendered contact/_quick_view_contact_info (1.7ms) 
Rendered contact/_quick_view_contact_info (2.2ms) 
Rendered contact/_quick_view_contact_info (1.5ms) 
Rendered contact/_quick_view_contact_info (2.0ms) 
Rendered contact/_quick_view_contact_info (1.7ms) 
Rendered contact/_quick_view_contact_info (1.8ms) 
Rendered contact/_quick_view_contact_info (3.6ms) 
Rendered contact/_quick_view_contact_info (2.2ms) 
Rendered contact/_quick_view_contact_info (2.2ms) 
Rendered contact/_quick_view_contact_info (1.9ms) 
Rendered contact/_quick_view_contact_info (1.7ms) 
Rendered contact/_quick_view_contact_info (2.0ms) 
Rendered contact/_quick_view_contact_info (2.1ms) 
Rendered contact/_quick_view_contact_info (1.9ms) 
Completed in 308ms (View: 104, DB: 27) | 200 OK [http://localhost/contact] 

Répondre

4

J'ai fait un peu plus de recherche et a trouvé la réponse. Je mets à jour ceci pour ceux qui chercheront plus tard. La réponse longue est dans this blog post.

Il semble que lorsque vous effectuez une recherche qui a deux jointures et une limite, ActiveRecord doit d'abord interroger la table principale pour obtenir les ID des lignes à renvoyer, puis refaire la requête en utilisant uniquement les ID afin d'appliquer la limite.

Depuis que j'utilisais will_paginate, c'est ce qui s'est passé comme will_paginate utilisé limit requêtes pour faire la pagination.

Questions connexes