zoukankan      html  css  js  c++  java
  • [技术博客] 数据库1+N查询问题

    作者:庄廓然

    问题简述

    本次开发过程中我们用到了rails的orm框架,使用orm框架可以很方便地进行对象的关联和查询,例如查询一个用户的所有关注的社团可以用一下语句:

    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
    

    但是如果你要返回一个社团列表,并且列表中包含关注该社团的人数,直接调用一下语句会导致查询效率降低

    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问题

    问题解决

    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对应的是关注者的个数

    {126833941=>1, 386008940=>2}
    

    没有记录的社团对应的关注者就是0.

    所以只用了一条查询记录便找到了所有社团的关注者的数量,提高了查询效率

    改正后的代码

    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
    
  • 相关阅读:
    background及background-size
    -ms-,-moz-,-webkit-,-o-含义
    &:first-of-type含义
    ES6的Promise对象
    LightOJ 1029 Civil and Evil Engineer最小生成树和最大生成树
    快速幂模板
    poj2965 The Pilots Brothers' refrigerator 枚举或DFS
    poj1753Flip Game(枚举+DFS)
    POJ 1751Highways
    HDU 1875 畅通工程再续 prim模板题
  • 原文地址:https://www.cnblogs.com/buaareadsun/p/10870385.html
Copyright © 2011-2022 走看看