王炸科技头像

Rails3中生MySQLsubquery的秘技

来源:
       

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

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

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

  所以在Application層(PHPorRails)下兩次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多達萬,顯然這招就效了。除了慢之外,還製造一堆無用物件浪費記憶體空間…

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

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

  favorite_count=Favorite.where(:book_id=>Book.where(:user_id=>user.id)).select("distinctbook_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取代兩個SELECTSUBQUERY不是萬靈丹,因為大多時候JOIN蠻多時候比SUBQUERY有效率,但SUBQUERY好寫蠻多的,可偷吃步…SUBQUERY適可而止,太多層SUBQUERY效能掉很兇(兩層其實就慢了...)。

  原文地址:Rails3中生MySQLsubquery的秘技,感谢原作者分享。