[技术博客] 数据库1+N查询问题
2024-09-02 03:59:58
作者:庄廓然
问题简述
本次开发过程中我们用到了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_id
,value
对应的是关注者的个数
{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
最新文章
- 在CentOS上安装并运行SparkR
- nginx 使用
- Angular实现瀑布流的库angular-deckgrid
- ionic 项目笔记
- AngularJS开发指南3:Angular主要组成部分以及如何协同工作
- jQuery基础知识--Form基础
- 转载:JAVA 正则表达式 (超详细)
- [原创].NET 分布式架构开发实战之一 故事起源
- USACO 1.5 Prime Palindromes
- windows MySQL 5.7 导出表方法记录
- cs231n --- 3 : Convolutional Neural Networks (CNNs / ConvNets)
- C#多线程编程(5)--线程安全1
- 经典栈溢出之MS060-040漏洞分析
- Linux环境搭建 | 手把手教你如何安装CentOS7虚拟机
- Linux系统vim几个常见配置
- 基于Web的漏洞利用
- kolla-ansible配置cinder 的ceph的多种后端存储池【转】
- L0/L1/L2范数(转载)
- 使用GPStracker自建卫星定位跟踪平台
- CH 2101 - 可达性统计 - [BFS拓扑排序+bitset状压]
热门文章
- Mysql连接数过多、Mysql连接错误过多的问题处理
- Docker 0x06: Docker Volume卷
- aws centos系统磁盘扩容
- React源码 Suspense 和 ReactLazy
- Unity基础功能:粒子特效(Shuriken)
- jvm内存模型-和内存分配以及jdk、jre、jvm是什么关系(阿里,美团,京东)
- 自定义微信小程序swiper轮播图面板指示点的样式
- Linux-导入已安装的Linux系统
- python基础语法11 内置模块time,datatime,random,os,sys,hashlib模块
- 如何使用h5py读入数据