[技術博客] 數據庫1+N查詢問題

做者:莊廓然數據庫

問題簡述

本次開發過程當中咱們用到了rails的orm框架,使用orm框架能夠很方便地進行對象的關聯和查詢,例如查詢一個用戶的全部關注的社團能夠用一下語句:ruby

list = @user.followed_clubs

#user.rb模型中添加
#user和club是多對多的關係,一個user能夠關注多個club,一個club也能夠有多個關注者
has_many :user_follow_clubs, dependent: :destroy 
has_many :followed_clubs, through: :user_follow_clubs, source: :club

#club.rb模型中添加
has_many :user_follow_clubs, dependent: :destroy
has_many :follow_users, through: :user_follow_clubs, source: :user

可是若是你要返回一個社團列表,而且列表中包含關注該社團的人數,直接調用一下語句會致使查詢效率下降app

list = @user.followed_clubs
result = []
list.each do |club|
    result.append(
    {
        club_id: club.id,
        followers: club.follow_users.count 
        #該語句會致使在每一個club中調用以下sql語句
    }
    )
end
SELECT COUNT(*) FROM `users` INNER JOIN `user_follow_clubs` 
ON `users`.`id` = `user_follow_clubs`.`user_id` WHERE `user_follow_clubs`.`club_id` = xxxx

也就是查詢一個社團列表調用了N次額外的查詢。框架

查詢主數據,是1次查詢,查詢出n條記錄;根據這n條主記錄,查詢從記錄,共須要n次,因此叫數據庫1+n問題code

問題解決

group的方法簡化查詢

list = @user.followed_clubs.ids
count_hash = UserFollowClub.where(club_id: list).group(:club_id).count
SELECT COUNT(*) AS count_all, `user_follow_clubs`.`club_id` AS user_follow_clubs_club_id FROM `user_follow_clubs` WHERE `user_follow_clubs`.`club_id` IN (1033447816, 126833941, 386008940) GROUP BY `user_follow_clubs`.`club_id`

最終獲得一個hash,key對應的是club_idvalue對應的是關注者的個數orm

{126833941=>1, 386008940=>2}

沒有記錄的社團對應的關注者就是0.對象

因此只用了一條查詢記錄便找到了全部社團的關注者的數量,提升了查詢效率blog

改正後的代碼

list = @user.followed_clubs
id_list = list.ids
count_hash = UserFollowClub.where(club_id: id_list).group(:club_id).count
list.each do |club|
    result.append(
    {
        club_id: club.id,
        followers: count_hash[club.id]
    }
    )
end
相關文章
相關標籤/搜索