2015-05-05 13 views
10

Źródła:Rails 3 dodając nazwę bazy danych do tabeli sprawia, że ​​zawiera domyślne dla chętnych obciążenia

Mój projekt jest w kierunku posiadania wielu baz danych (obecnie na tym samym serwerze) , i chciałbym móc dołączyć między tymi bazami danych. Aby to zrobić, należy dodać nazwę bazy danych, aby prefiks tabeli tak:

class FirstBase < ActiveRecord::Base 
    def self.table_name_prefix 
     "DBNAME.t_" 
    end 

    establish_connection :firstdb 
end 

class User < FirstBase 
    has_many :user_roles 
end 

class UserRole < FirstBase 
    belongs_to :user 
end 

Dodanie nazwy tabeli przedrostek wydaje się wpływać na zachowanie domyślne zawiera tego samego zapytania, nawet w obrębie tej samej bazy danych . Rozważmy User.includes(:user_roles).first

bez nazwy tabeli przedrostek:

obciążenia użytkownika (67.1ms) SELECT * FROM t_userst_users LIMIT 1 UserRole obciążenie (84.5ms) SELECT * FROM t_user_rolest_user_roles GDZIE t_user_roles... user_id NA (1)

Z Nazwa tabeli początkowy:

SQL (76.8ms) select distinct DBNAME. t_users .id FROM DBNAME. t_users LEFT OUTER DOŁĄCZ DO DBNAME. t_user_roles ON DBNAME. t_user_roles. user_id = DBNAME. t_users. id LIMIT 1

SQL (66.4ms) WYBIERZ DBNAME. t_users. id AS t0_r0, DBNAME. t_users. email AS t0_r1, DBNAME. t_user_roles. id AS t1_r0, DBNAME. t_user_roles. user_id AS t1_r1 OD DBNAME. t_users LEFT OUTER DOŁĄCZ DO DBNAME. t_user_roles ON DBNAME. t_user_roles. user_id = DBNAME. t_users. id WHERE DBNAME. t_users. id IN (1)

Innymi słowy, domyślne zachowanie wywołań zostało zmienione z preload na chętne ładowanie.

Czy ktoś wie, dlaczego zmienia się domyślne zachowanie? Musi być coś na temat dodawania nazwy bazy danych, która sprawia, że ​​Railsy są zmuszone do ładowania, ale nie rozumiem dlaczego. Jestem także zaskoczony tym, ponieważ wyobrażam sobie, że nie jest niczym niezwykłym dodanie nazwy bazy danych w. Mogę brutalnie wymuszać naprawę tego w naszej bazie kodu, zmieniając wszystkie załączniki, aby wstępnie załadować, ale chciałbym zrozumieć, co się tutaj dzieje. Czy istnieje sposób na zmianę domyślnego zachowania?

+0

Czy "FirstBase" jest klasą abstrakcyjną? ('self.abstract_class = true'). Domyślam się, że logika STI może zakłócać generowanie sql tutaj. Może spróbuj wyodrębnić tę logikę w module/zagadnieniu? (zwróć też uwagę, że modele z określonymi nazwami używają 'table_name_prefix 'swojego modułu nadrzędnego). Z drugiej strony, AFAIK faktyczny SQL wygenerowany przez 'includes' jest" niezdefiniowanym zachowaniem "i zależy od twojego adaptera DB. –

Odpowiedz

1

Problem polega na tym, że table_name_prefix wprowadza kropkę. To dezorientuje logikę, która próbuje określić, czy powinna ona wstępnie ładować, czy też być obciążona. To jest błąd Rails 3 i został rozwiązany w Rails 4.Jeśli potrzebujesz określonego zachowania w Railsach 3, musisz wyraźnie określić preload lub eager_load, jak wskazałeś w swoim pytaniu.

W ActiveRecord::Relation, exec_queries dzwoni pod numer eager_loading?, aby zdecydować, czy powinien on być bardzo obciążony. Wymaga to references_eager_loaded_tables? który wykorzystuje tables_in_string aby spróbować znaleźć nazwy tabeli w zapytaniu SQL, które nie są częścią połączonych tabelach:

# ActiveRecord::Relation#references_eager_loaded_tables? 
(tables_in_string(to_sql) - joined_tables).any? 

Sposób tables_in_string była błędna, ponieważ nie zawsze poprawnie analizować SQL . Kod ten może być używany do przeglądu co myśli są nazwy tabel w zapytaniu SQL:

relation = User.includes(:user_roles) 
relation.send(:tables_in_string, relation.to_sql) 

z nazwą DBNAME.t_ tabeli prefiksu, to daje ["DBNAME", "t_users"] jako nazw tabel, co jest nie tak. Powinno to dać ["DBNAME.t_users"]. Podobny problem został udokumentowany w ActiveRecord query changing when a dot/period is in condition value. Doprowadziło to do zmian w ActiveRecord::Relation, które odeszły od użycia tables_in_string podczas podejmowania decyzji, czy załadować wstępnie lub niecierpliwie.

+0

Dziękuję za szczegółową odpowiedź! Dokładnie to, czego szukałem. – raja

Powiązane problemy