获取所有用户的一组user_details的最佳方法

时间:2016-04-28 09:53:07

标签: sql ruby-on-rails

考虑以下情况,我有两个表UsersUserDetails

User
has_one :user_detail

UserDetail
belongs_to :user

我有一个案例,我必须搜索user_details并返回一个user_details集合的结果。现在,我希望获得此user的所有相关user_details条记录。

我知道的一种方法是从user_id结果中获取user_details,并在User模型中搜索此ID。

relevant_user_ids = user_details_search_result.pluck(:user_id)
User.where(id: relevant_user_ids)

其他方式是

User.joins(:user_detail)
.where("user_details.search_column = ?",search_requirement).

我想知道User表是否很庞大,加入user_details会显着减慢速度吗?

哪一个更好,还有其他办法。

1 个答案:

答案 0 :(得分:1)

$("#upd_info").on('click', function()
      {
        var upd_name = $("#name_upd").val();
        var upd_dob = $("#dob_upd").val();
        var upd_phone = $("#phone_upd").val();
        var upd_address = $("#address_upd").val();
        $.ajax({
          url: 'upd_patient.php',
          data: {upd_id: id, n: upd_name, d: upd_dob, p:upd_phone, a:upd_address},
          type: 'POST',
          dataType: 'JSON',

          success:function(res3)
          {
            $( "#dialog" ).dialog( "close" );
            //here I need to access td of class nameid and change the value
          },
          error:function(res3)
          {
            console.log("Error Updating info");
          }
        });

也是一种选择。这可能比User.includes(:user_detail).where(user_details: {search_column: search_requirement}) (您的第二个示例)更快,具体取决于以下后续查询。即如果你以后要访问UserDetails属性,那么包含更快但是你需要更大的内存或根本没有这个,因为它会急切加载所有User和UserDetails记录,而不是加入哪个只会懒得加载用户记录,但如果您以后要访问UserDetail记录,则需要调用其他数据库查询。

我不确定.join的速度有多快,但是如果你关心记忆,那么第一个使用pluck的例子就是我想要走的路。

奇怪的是,我尝试过运行测试:

(SSD,SQLite,Rails 4.2)

场景1(不调用关联记录)

.pluck

场景2(调用相关记录):

Post.destroy_all
User.destroy_all
time = {}

user = User.create!(name: 'foo')
5.times{ Post.create(title: 'hello', user: user) }

start_time = Time.now
1000.times do
  user_ids = User.where(name: 'foo').pluck(:id); nil
  posts = Post.where(user_id: user_ids); nil
  posts.each{|post| 100.times{ puts post.title } }; nil
end
time[:using_pluck] = (Time.now - start_time) / 1000

start_time = Time.now
1000.times do
  posts = Post.joins(:user).where(users: {name: 'foo'}); nil
  posts.each{|post| 100.times{ puts post.title } }; nil
end
time[:using_joins] = (Time.now - start_time) / 1000

start_time = Time.now
1000.times do
  posts = Post.joins(:user).where(users: {name: 'foo'}); nil
  posts.each{|post| 100.times{ puts post.title } }; nil
end
time[:using_includes] = (Time.now - start_time) / 1000

puts time.to_yaml
# ---
# :using_pluck:    0.002787939
# :using_joins:    0.0027696689999999998
# :using_includes: 0.0027880739999999998

在场景1中(不调用关联记录),Post.destroy_all User.destroy_all time = {} user = User.create!(name: 'foo') 5.times{ Post.create(title: 'hello', user: user) } start_time = Time.now 1000.times do user_ids = User.where(name: 'foo').pluck(:id); nil posts = Post.where(user_id: user_ids); nil posts.each{|post| 100.times { puts post.user.name } }; nil end time[:using_pluck] = (Time.now - start_time) / 1000 start_time = Time.now 1000.times do posts = Post.joins(:user).where(users: {name: 'foo'}); nil posts.each{|post| 100.times { puts post.user.name } }; nil end time[:using_joins] = (Time.now - start_time) / 1000 start_time = Time.now 1000.times do posts = Post.includes(:user).where(users: {name: 'foo'}); nil posts.each{|post| 100.times { puts post.user.name } }; nil end time[:using_includes] = (Time.now - start_time) / 1000 puts time.to_yaml # --- # :using_pluck: 0.006066561 # :using_joins: 0.006919676 # :using_includes: 0.00473808 稍微(我认为会很多)比.joins更快,因为在.includes中它不需要执行额外的查询以获取关联记录,而.joins仍然可以获取附加记录。但是,在场景2(调用关联记录)中,.includes.includes快,因为.joins对数据库执行其他查询以获取关联记录,而.joins已经.includes急切地加载它,因此已经在记忆中。