2017-02-21 3 views
0

Действительно ли Rails кэширует результат запроса? The documentation говорит тот же запрос никогда не будет выполняться дважды на тот же запрос:Выполняет ли запрос базы данных Rails Really Cache?

1,7 SQL Caching

Второй раз тот же запрос выполняется в базе данных, это на самом деле не собирается попасть в базу данных , В первый раз, когда результат возвращается из запроса, он сохраняется в кеше запросов (в памяти), а во второй раз он извлекается из памяти.

Я сделал эксперимент для доказательства того, что на самом деле Rails кэшировать запрос:

def test 
    data = "" 
    User.find(1).update(first_name: 'Suwir Suwirr') 
    data << User.find(1).first_name 
    data << "\n" 

    User.find(1).update(first_name: 'Pengguna') 
    data << User.find(1).first_name 
    data << "\n" 

    render plain: data 
    end 

Если результат кэшируется, я хотел бы получить тот же результат для каждого User.find(1). Однако в результате Rails фактически не кэшировал запрос; я ожидал, что update не отражается на результат, так как он был «в кэше»:

Suwir Suwirr 
Pengguna 

Но консоль говорит, что он кэшируется: (Пожалуйста, выделите CACHE слово)

Started GET "/diag/test" for 10.0.2.2 at 2017-02-21 10:30:16 +0700 
Processing by DiagController#test as HTML 
    User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 4], ["LIMIT", 1]] 
    User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 
    (0.1ms) BEGIN 
    SQL (0.4ms) UPDATE "users" SET "first_name" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["first_name", "Suwir Suwirr"], ["updated_at", 2017-02-21 03:30:16 UTC], ["id", 1]] 
    (16.5ms) COMMIT 
    User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 
    CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 
    (0.1ms) BEGIN 
    SQL (0.3ms) UPDATE "users" SET "first_name" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["first_name", "Pengguna"], ["updated_at", 2017-02-21 03:30:16 UTC], ["id", 1]] 
    (0.9ms) COMMIT 
    User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 
    Rendering text template 
    Rendered text template (0.0ms) 
Completed 200 OK in 380ms (Views: 3.5ms | ActiveRecord: 21.9ms) 

Итак, мой вопрос, действительно ли Rails кэширует результат запроса? Или, только несколько результат запроса по некоторому запросу?

Update: Использование Batch #update_all

Я сделал еще один эксперимент, чтобы "обмануть" логику запроса. Теперь Rails не «кэширует» запрос. Почему такое поведение может случиться?

# Controller 
    def test 
    data = "" 
    User.where(id: 1).update_all(first_name: 'Suwir Suwirr') 
    data << User.find(1).first_name 
    data << "\n" 

    User.where(id: 1).update_all(first_name: 'Pengguna') 
    data << User.find(1).first_name 
    data << "\n" 

    logger.info 'hi' 

    render plain: data 
    end 

# Console 
Started GET "/diag/test" for 10.0.2.2 at 2017-02-21 10:45:43 +0700 
Processing by DiagController#test as HTML 
    User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 4], ["LIMIT", 1]] 
    SQL (13.8ms) UPDATE "users" SET "first_name" = 'Suwir Suwirr' WHERE "users"."id" = $1 [["id", 1]] 
    User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 
    SQL (2.9ms) UPDATE "users" SET "first_name" = 'Pengguna' WHERE "users"."id" = $1 [["id", 1]] 
    User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 
hi 
    Rendering text template 
    Rendered text template (0.0ms) 
Completed 200 OK in 28ms (Views: 0.8ms | ActiveRecord: 17.8ms) 

# Browser result 
Suwir Suwirr 
Pengguna 
+1

Прочитать (выберите, где, найти) запрос кешируются. Обновление и уничтожение не кэшируются. – coderhs

ответ

1

Я был глуп.

Да, Rails действительно кэширует запрос, но update и destroy аннулируют его кеш запросов. в основном итерирует каждую запись с помощью update.

Я пробовал эксперимент, действительно «обманывая» механизм запросов ActiveRecord. И да, это работает.

# Controller 
    def test 
    data = "" 
    ActiveRecord::Base.connection.execute('UPDATE "users" SET "first_name" = \'Suwir Suwirr\' WHERE "users"."id" = 1') 
    data << User.find(1).first_name 
    data << "\n" 

    ActiveRecord::Base.connection.execute('UPDATE "users" SET "first_name" = \'Pengguna\' WHERE "users"."id" = 1') 
    data << User.find(1).first_name 
    data << "\n" 

    render plain: data 
    end 

# Browser 
Suwir Suwirr 
Suwir Suwirr 
Смежные вопросы