# performance

## `select`, `pluck`

`pluck` will load an array of column, and is faster than `select`.

`select` is \~10X slower than `pluck`, because of creating objects.

```ruby
User.select(:id).to_a
# => User Load (0.9ms)  SELECT id FROM "users"
# => [#<User id: 12>, #<User id: 42>, #<User id: 1>, #<User id: 24>, #<User id: 200>, ...]
```

```ruby
User.pluck(:id)
# => (0.9ms)  SELECT "users"."id" FROM "users"
# => [12, 42, 1, 24, 200, ..., 365]

User.pluck(:first_name, :last_name, :email)
# =>   (2.2ms)  SELECT "users"."first_name", "users"."last_name", "users"."email" FROM "users"
# => [[nil, nil, "jeff@gmail.com"], ['joe', nil, "joe.brown@gmail.com"], ["Edward", "Stanza", "ed@email.com"], ...]
```

<http://gavinmiller.io/2013/getting-to-know-pluck-and-select/>

## How long to build ActiveRecord models

10.4ms for db query, but total 143ms for the whole process.

```ruby
User.all.to_a
# => User Load (10.4ms)  SELECT "users".* FROM "users"
# => [#<User id: 263, ... >, #<User id: 264, ... >, #<User id: 265, ... >, ... ]

puts Benchmark.measure { User.all.to_a }
    user    system     total        real
0.143333  0.000000  0.143333 (  0.163123)
```

## Preload, Eagerload, Includes and Joins

`preload`, `eager_load`, `includes` = eager loading (prevent n+1)

1. `Preload` loads the association data in a **separate query**.

   ```ruby
    User.preload(:posts).to_a
    # =>
    SELECT "users".* FROM "users"
    SELECT "posts".* FROM "posts"  WHERE "posts"."user_id" IN (1)
   ```

   Since `preload` always generates two sql, we can’t use posts table in where condition.

   ```ruby
    User.preload(:posts).where("posts.desc='ruby is awesome'")
    # =>
    SQLite3::SQLException: no such column: posts.desc:
   ```
2. `eager_loading` loads all association in a **single** query using **LEFT OUTER JOIN**.

   ```ruby
    User.eager_load(:posts).to_a    
    # =>
    SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0,
           "posts"."title" AS t1_r1, "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3
    FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
   ```
3. `Includes`

   Behaves based on situations, intelligent!

   ```ruby
   Blog.includes(:posts)
   # =>
   Blog Load (2.8ms)  SELECT "blogs".* FROM "blogs"
   Post Load (0.7ms)  SELECT "posts".* FROM "posts" WHERE "posts"."blog_id" IN (1, 2, 3)

   Blog.includes(:posts).where(name: 'Blog 1').where(posts: {title: 'Post 1-1'})
   # =>
   SQL (0.2ms)  SELECT "blogs"."id" AS t0_r0, "blogs"."name" AS t0_r1, "blogs"."author" AS t0_r2, "blogs"."created_at" AS t0_r3, "blogs"."updated_at" AS t0_r4, "posts"."id" AS t1_r0, "posts"."title" AS t1_r1, "posts"."created_at" AS t1_r2, "posts"."updated_at" AS t1_r3, "posts"."blog_id" AS t1_r4 FROM "blogs" LEFT OUTER JOIN "posts" ON "posts"."blog_id" = "blogs"."id" WHERE "blogs"."name" = ? AND "posts"."title" = ?  [["name", "Blog 1"], ["title", "Post 1-1"]]
   ```

   `includes` + `references` = `eager_loading`
4. `Joins` brings association data using **inner join**.

   ```ruby
    User.joins(:posts)
    # =>
    SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
   ```

## Intention for eager loading

```ruby
# Give me users with polish addresses and preload only polish addresses
User.includes(:addresses).where("addresses.country = ?", "Poland")

# Give me users with polish addresses and preload only polish addresses(same, but inner join)
User.joins(:addresses).where("addresses.country = ?", "Poland").includes(:addresses)

# Give me users with polish addresses but preload all of their addresses.
User.joins(:addresses).where("addresses.country = ?", "Poland").preload(:addresses)
```

## Too much query

| Array                          | DB query                 |
| ------------------------------ | ------------------------ |
| sort\_by                       | order                    |
| .select { c c.label != 'All' } | .where.not(label: 'All') |

<http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html>

<http://blog.arkency.com/2013/12/rails4-preloading/>

<http://collectiveidea.com/blog/archives/2015/03/05/optimizing-rails-for-memory-usage-part-3-pluck-and-database-laziness>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://huang-jason.gitbook.io/ruby-rails-syntax/performance.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
