论坛首页 Java企业应用论坛

用n+1句sql解决多表查询反而比1句联合sql要好

浏览 24705 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-10-19  
多对一 n+1sql问题的是指下列情况。假设系统系统中存在两张表,学生表(n)和老师表(1),学生表和老师表是多对一关系。
学生表的字段为 sid,sname,tid
老师表的字段 为 tid tname
两张表通过tid外键关联。
现在假设一个页面需要浏览学生记录,同时要显示这个学生对应的老师名称,有两种查询方法。
1)一种方法 n+1句sql,先查询select * from 学生表。再根据结果记录查询 select * from 老师表 where tid =?
2)另外一种方法 是建立一条联合查询语句 select * from 学生表 a inner join 老师表 b on a.tid=b.tid。


在没有分页的情况下,第二种方法的效率比第一种方法高,然而在有分页的情况下,反而是n+1句sql的执行效率高。

假设两张表都没有索引,学生表有10000条记录,老师表为1000条记录,每个页面显示100条记录。那么第一种方法数据库的执行的时间复杂度是 10000+100*1000。
第二种方法执行的时间复杂度 是10000×1000。
双方的差别接近1000左右。
在有索引的情况下,双方的差别没有这么大,但也是第一种情况的算法复杂度小。

所以在系统存在分页(绝大部分的系统均存在分页)的情况下,我们还是采取n+1句sql语句进行查询的效率高。
而且第一种方法也是一种扩展性比较良好的方法。假设老师表的数据过多,我们需要把老师表进行水平切割成100个表,那么第一种方法的扩展性是比较好的。第二种方法只有重新修改
   发表时间:2011-10-19  
这种东西都是看情况才能决定使用何种方式的,没有人敢绝对的下定论
0 请登录后投票
   发表时间:2011-10-19  
liubey 写道
这种东西都是看情况才能决定使用何种方式的,没有人敢绝对的下定论

所以我的前提 是有分页的情况
0 请登录后投票
   发表时间:2011-10-19   最后修改:2011-10-19
你以为网络传输是白送的?
0 请登录后投票
   发表时间:2011-10-19  
抛出异常的爱 写道
你以为网络传输是白送的?


select * from 老师表 where tid in (t1, t2, t3 ... tn)

1 + 1 sql,网络也不成问题了
0 请登录后投票
   发表时间:2011-10-19  
李华植的《海量数据库解决方案》 第5章 局部范围扫描(partial range scan)
应该有这种拆分,合并的原理解析

http://product.china-pub.com/53793#ml
0 请登录后投票
   发表时间:2011-10-19  
抛出异常的爱 写道
你以为网络传输是白送的?

n+1的确在网络方面会多耗一点资源,但是我觉得在大部分应用中,这些资源的消耗是可以补偿回来的。相对来说,对db的负担更加减轻了
0 请登录后投票
   发表时间:2011-10-19  
ytrgmj 写道
抛出异常的爱 写道
你以为网络传输是白送的?

n+1的确在网络方面会多耗一点资源,但是我觉得在大部分应用中,这些资源的消耗是可以补偿回来的。相对来说,对db的负担更加减轻了


网络IO补硬盘IO好吧在极端状态下可以补回来。
0 请登录后投票
   发表时间:2011-10-19  
weifly 写道
抛出异常的爱 写道
你以为网络传输是白送的?


select * from 老师表 where tid in (t1, t2, t3 ... tn)

1 + 1 sql,网络也不成问题了

然后在内存里把老师再对应到每个学生上。
0 请登录后投票
   发表时间:2011-10-19  
CurrentJ 写道
weifly 写道
抛出异常的爱 写道
你以为网络传输是白送的?


select * from 老师表 where tid in (t1, t2, t3 ... tn)

1 + 1 sql,网络也不成问题了

然后在内存里把老师再对应到每个学生上。

好吧 你是打算 用hibernate。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics