Home > Database > Mysql Tutorial > body text

Rails 3 中生 MySQL subquery 的秘技

WBOY
Release: 2016-06-07 16:36:13
Original
876 people have browsed it

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
Copy after login

因為你無法知道 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
Copy after login

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

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

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 效能掉很兇(兩層其實就慢了...)。
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template