Ruby 板


LINE

出自我的Blog http://lightyror.blogspot.com/2006/10/sql-activerecord.html 有些时候我在想,到底 Active Record 底层是怎麽干的呢?在使用方便之余,有没有一些底层的作法是不好的呢?今天就特别花点时间去看看到底 Active Record 是怎麽搞的,我先测试看看最多人使用的撷取(Retrieve)功能。 假设有几个 Model :User,Blog,info,friends。 User 跟 Info 呈现 1:1 关系,User跟Blog呈现 1:n 关系,User跟 Friend 呈现 n:m 关系。所有的Model设定都采取预设值,所有关系都设定OK了。 单独取一个 entry : 如果我们下达这样的指令 User.find(1) ,出现的 SQL 是这样的 SELECT * FROM users WHERE (users.id = 1) LIMIT 1 看到这个SQL,我就对整体效率放心了。因为我本来还以为 Active Record 有可能这个可能性一次 select 出所有相关的 table SELECT * FROM users WHERE (users.id = 1) LIMIT 1 SELECT * FROM infos WHERE (infos.user_id = 1) SELECT * FROM blogs WHERE (blogs.user_id = 1) .......... 如果真的这样作会超级耗 memory ,但是好家在 Active Record 只会 select 有用到的 relation table 。所有的 relation ship 都是有用到才会去 select ,所以我可以尽情的使用 relationship,反正只有需要的时候才会去 call DB。 SQL injection 如果下达 User.find_by_email(" '[email protected]") 这样SQL injection 的用法,我们发现到 SQL 会变成 SELECT * FROM users WHERE (users.`email` = '\'[email protected]' ) LIMIT 1 也就是使用 find_by 是会自动跳脱 SQL 危险符号,值得鼓励。 以後都在已经使用 a = User.find(1) 的前提下进行。 取出 1:1 relation 如果我们下达这样的指令 a.info ,出现的 SQL SELECT * FROM infos WHERE (infos.user_id = 1) LIMIT 1; 不使用 join 而是使用两个 select 。 取出 1:m relation 如果我们下达这样的指令 a.blogs ,出现的 SQL 是这样的 SELECT * FROM blogs WHERE (blogs.user_id = 1) 也是不使用 join 而是使用两个 select 。 取出 n:m relation 如果我们下达这样的指令 a.friends ,出现的 SQL 是这样的 SHOW FIELDS FROM friends SELECT * FROM users INNER JOIN friends ON users.id = friends.friend_user_id WHERE (friends.user_id = 1 ) 他一开始先作 User.find(1) 的工作,然後使用一个 inner join 来表达 n:m 的关系。 当 column 有 BLOB 栏位时 譬如 User 这个 Model ,User 里面有 photo 这个 Blob column(将图片存到资料库),以下是 irb 出现的状况 >> a = User.find(11) => #"\000\004\000\001\001\000@ \000\000\000\002\000\000\000\000\000 .......... 很多页" , "name"=>"a", "id"=>"11", "email"=>"b"} Active Record 出现的SQL 是 SELECT * FROM users WHERE (users.id = 11) LIMIT 1 一般来说我们遇到这个栏位都会使用 SELECT name , email FROM users WHERE (users.id = 11) LIMIT 1 特别指定某些栏位的方式来撷取资料,原因是为了没用到 BLOB的时候,避免撷取 BLOB 太花时间了。 结语 从上面的结论来看,Active Record 处理各种关系的 撷取(Retrive)的底层作法都不会太差,并且他会根据等到使用到的 relation 才会进行 DB access,而不是一次将所有的 relation table 取出来。 第一个可能遇到的问题在於,毕竟Active Record 是跨DB的pattern ,无法做到针对个别 DB 作最佳化。不过我们还是可以对效能瓶颈的SQL,用 find_by_sql('最佳化的SQL') 来作最佳化的工作。不过这是确定瓶颈在於某个 SQL query 的情况下才需要作的事情。如果每个都要写 SQL 那还不如回去用PHP。 另外一个可能遇到的问题是因为 Active Record 为了达到方便的用途,直接使用 select * 这样的作法。当你的 DB column 里面有 BLOB 这样的栏位时,不管对 DB 资料传输,或是整个 Model 占用 memory 消耗都会有严重的影响。 如果可以的话,尽量将 BLOB 这样的栏位跟原来的 table 分离成另外一个 table ,并且跟原 table 作 1:1 的关系,等到真的有用到这个栏位时,再去取出这个 table 较好。像是上面的例子,虽然很多页面都会用到 User 这个 Model ,但是几乎绝大部份没有使用到 photo 的属性。所以我们可以独立出一个 Photo Model ,跟 User 呈现 1:1 关系,等到有用到的时候再使用 User.photo 这样的作法来使用。这样可以有效率的减少 photo 占用的记忆体,跟传输消耗的时间。 -- lighty RoR 是一个介绍 lighttpd , SQLite , Ruby and Rails 的 Blog http://lightyror.blogspot.com/ --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 218.170.38.72 ※ 编辑: giive 来自: 218.170.38.72 (10/22 08:53)
1F:推 qrtt1:咳! 用php也可以不写sql啊。 10/22 09:36
2F:推 PttHuge:用toplink也可以不写sql呀 10/22 13:00







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BabyMother站内搜寻

TOP