從 SQL 看 ActiveRecord 實做方式 (2) :Count

看板Ruby作者 (lala)時間18年前 (2006/10/30 13:04), 編輯推噓0(001)
留言1則, 1人參與, 最新討論串1/1
出自我的Blog http://lightyror.blogspot.com/2006/10/sql-activerecord-2-count.html 自從上次寫了 從 SQL 看 ActiveRecord 實做方式 ,我養成了寫完程式,會順便看 SQL 的好習慣。今天早上我花點時間來測試一下,計算資料庫數量的多寡的重要函式 Count 。之前我要寫數量多寡都是直接用 .size 來寫。像是找出 User 裡面名字叫做 a 的所有資料數量 User.find_all_by_nickname('a').size 結果出現的 SQL 是 User Load (0.000444) SELECT * FROM users WHERE (users.`nickname` = 'a' ) 媽呀,真是刺激。也就是說,他會將所有的 nickname 為 a 的資料全部傳出來(1),塞給一個 array(2) ,然後計算 array 的數量大小。假設資料數量一大起來,1的傳輸時間會大幅度的增加,2的 array 所佔用的記憶體也會暴增。 再來,我來測試一下,關聯性 has_many 遇到計算數量時候的作法 a = User.find(1) a.blogs.size 出現的 SQL 是 User Load (0.000339) SELECT * FROM users WHERE (users.id = 1) LIMIT 1 Blog Load (0.000320) SELECT * FROM blogs WHERE (blogs.user_id = 1) 媽呀,真是跟上面一樣刺激,會遇到的問題也跟上面一樣麻煩。也就是說,用 .size 的作法完全不可取。 我們換個方式,我看到了關聯性 has_many 支援一個 function ,就是在has_many 後面加入一個 _count a = User.find(1) a.blogs_count 出現的 SQL 是 User Load (0.000339) SELECT * FROM users WHERE (users.id = 1) LIMIT 1 Blog Load (0.000320) SELECT * FROM blogs WHERE (blogs.user_id = 1) 天呀,居然跟 .size 一樣,真是刺激的作法(有寫跟沒寫一樣)。 這個時候,臉上不禁出現三條線,那麼簡單的事情 Ruby on Rails 會沒考慮到?怎麼可能,我通常遇到這個問題時,會先 Chanllege 自己一下『應該是我不熟悉,而是沒有這個東西』。這時拿出居家旅行必備良書 Agile Web Programming with Rails 出來拜一拜,發現到如果我們使用 User.count(["nickname = ?" , "a"]) 出現的 SQL 是 SQL (0.000324) SELECT count(*) AS count_all FROM users WHERE (nickname = 'a') 而關聯性資料庫 a.blogs.count 出現的 SQL 是 SQL (0.000296) SELECT count(*) AS count_all FROM blogs WHERE (blogs.user_id = 1) 拉拉,就是這個就是這個。 在 DB 處理 select count(*) 本來就會比 select * 來得快而且省記憶體。並且在資料庫傳輸到程式語言裡面只傳一個數字遠比傳一組 array 來得快。傳到程式語言裡面變數佔用的記憶體也有天壤之別。 結論是請大量使用 .count ,而請不要使用 _count ,或是 .size 來計算資料庫數量的大小。 -- lighty RoR 是一個介紹 lighttpd , SQLite , Ruby and Rails 的 Blog http://lightyror.blogspot.com/ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.218.90.242

10/30 15:32, , 1F
經驗啊..寫的真好,感謝你的用心
10/30 15:32, 1F
文章代碼(AID): #15HOVcpF (Ruby)
文章代碼(AID): #15HOVcpF (Ruby)