欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

Rails 3 中生 MySQL subquery 的秘技

程序员文章站 2022-05-20 10:26:31
...

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://*.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 效能掉很兇(兩層其實就慢了...)。