视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Rails3中生MySQLsubquery的秘技
2020-11-09 13:09:39 责编:小采
文档


http://blog.rocodev.com/posts/13-mysql-subquery-in-rails-3 有時候設計 Rails Application 時,某些 JOIN 的語法並不是那麼好寫。(不管是手刻,或者是透過 ORM 下出來。) 所以在 Application 層( PHP or Rails) 下兩次 SELECT 或者是用 subquery 往往

http://blog.rocodev.com/posts/13-mysql-subquery-in-rails-3

有時候設計 Rails Application 時,某些 JOIN 的語法並不是那麼好寫。(不管是手刻,或者是透過 ORM 下出來。)

所以在 Application 層( PHP or Rails) 下兩次 SELECT 或者是用 subquery 往往會變成直覺下的取代方案。

舉個例子,有個功能叫做:我上架的書有被人 facvorite 的總數量。

一般開發者在不用 JOIN 的情況下,會寫出這樣的 code

 book_ids = Book.where(:user_id => user.id)
 favorite_count = Favorite.where(:book_id => book_ids).select("book_id").map(&:book_id).uniq.size

因為你無法知道 book_ids 怎麼拉出來丟 query,只好拉到 Application 層再塞回去用 IN 撈。數量小這樣的作法是還 okay….但…萬一 book_ids 多達萬,顯然這招就效了。除了慢之外,還製造一堆無用物件浪費記憶體空間…

而 Rails 3 背後強大的 Arel,其實提供了自動算出 subquery 的語法:

其實上面那一段可以改為這樣寫

 favorite_count = Favorite.where(:book_id => Book.where(:user_id => user.id)).select("distinct book_id").count

是的,在查詢語句裡面再下條件就會自動變成 subquery 了....

Favorite.where(:book_id => Book.where(:user_id => user.id))

http://stackoverflow.com/questions/5483407/subqueries-in-activerecord

幾個原則

  • 不是 JOIN 就是慢
  • 兩個 SELECT 不一定比 JOIN 快。(在以上 book_id 數量很大的 case 中)
  • 兩個 SELECT 有時候會比 JOIN 快。(在以上 book_id 數量很小的 case 中)
  • 有時候應該用 SUBQUERY 取代兩個 SELECT
  • SUBQUERY 不是萬靈丹,因為大多時候 JOIN 蠻多時候比 SUBQUERY 有效率,但 SUBQUERY 好寫蠻多的,可偷吃步…
  • SUBQUERY 適可而止,太多層 SUBQUERY 效能掉很兇(兩層其實就慢了...)。
  • 下载本文
    显示全文
    专题