2017-02-21 51 views
0

Rails是否實際緩存查詢結果? The documentation說,同樣的查詢將在同一請求永遠不會被執行兩次Rails是否真的緩存數據庫查詢?

1.7 SQL緩存

相同的查詢針對數據庫運行第二次,它實際上不是會打數據庫。第一次從查詢返回結果時,它將存儲在查詢緩存中(在內存中),第二次從內存中取出結果。

我做了一個實驗,以證明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_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

讀取(select,where,find)查詢被緩存。更新和銷燬不被緩存。 – coderhs

回答

1

我很蠢。

是的,Rails確實緩存了查詢,但是updatedestroy會使其查詢緩存失效。 update_all基本上是用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