mardi 5 mai 2015

Rails 3 adding database name to table makes includes default to eager load

Sources:

My project is moving towards having multiple databases (currently on the same server), and I would like to be able to join between these databases. In order to do this, I need to add the database name to the table prefix like so:

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

class User < FirstBase
    has_many :user_roles
end

class UserRole < FirstBase
    belongs_to :user
end

Adding the table name prefix seems to impact the default behavior of includes on the same query, even within the same database. Consider User.includes(:user_roles).first

Without table name prefix:

User Load (67.1ms) SELECT t_users.* FROM t_users LIMIT 1 UserRole Load (84.5ms) SELECT t_user_roles.* FROM t_user_roles WHERE t_user_roles.user_id IN (1)

With table name prefix:

SQL (76.8ms) SELECT DISTINCT DBNAME.t_users.id FROM DBNAME.t_users LEFT OUTER JOIN DBNAME.t_user_roles ON DBNAME.t_user_roles.user_id = DBNAME.t_users.id LIMIT 1

SQL (66.4ms) SELECT 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 FROM DBNAME.t_users LEFT OUTER JOIN DBNAME.t_user_roles ON DBNAME.t_user_roles.user_id = DBNAME.t_users.id WHERE DBNAME.t_users.id IN (1)

In other words, the default behavior of calling includes has changed from preload to eager load.

Does anyone know why the default behavior is changing? There must be something about adding the database name that makes Rails think we must eager load, but I don't see why. I'm also surprised to see this as I imagine it's not unusual to add the database name in. I can brute-force fix this in our codebase by changing all includes to preload, but I would like to understand what is happening here. Is there a way to change the default behavior?

Aucun commentaire:

Enregistrer un commentaire