我有以下ActiveRecord
查询
LoanApplication.joins(:case_status => :loan_case).where.not(case_code: nil).group("loan_cases.id, loan_cases.case_status").select("loan_cases.case_status, count(loan_applications.id)").order("loan_cases.rank ASC")
,如果使用.explain
细分,则会提供以下查询计划
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Sort (cost=2924.84..2924.85 rows=1 width=532)
Sort Key: loan_cases.rank
-> GroupAggregate (cost=0.43..2924.83 rows=1 width=532)
Group Key: loan_cases.id
-> Nested Loop (cost=0.43..2918.67 rows=1230 width=528)
-> Nested Loop (cost=0.14..1898.81 rows=1765 width=528)
Join Filter: (case_statuses.loan_case_id = loan_cases.id)
-> Index Scan using loan_cases_pkey on loan_cases (cost=0.14..12.45 rows=1 width=524)
Filter: (deleted_at IS NULL)
-> Seq Scan on case_statuses (cost=0.00..1423.03 rows=37066 width=8)
Filter: (deleted_at IS NULL)
-> Index Scan using loan_applications_pkey on loan_applications (cost=0.29..0.58 rows=1 width=4)
Index Cond: (id = case_statuses.loan_application_id)
Filter: ((deleted_at IS NULL) AND (case_code IS NOT NULL))
(14 rows)
或以下SQL查询
SELECT loan_cases.case_status, count(loan_applications.id) FROM
"loan_applications" INNER JOIN "case_statuses" ON
"case_statuses"."loan_application_id" = "loan_applications"."id" AND
"case_statuses"."deleted_at" IS NULL INNER JOIN "loan_cases" ON
"loan_cases"."id" = "case_statuses"."loan_case_id" AND
"loan_cases"."deleted_at" IS NULL WHERE
"loan_applications"."deleted_at" IS NULL AND
("loan_applications"."case_code" IS NOT NULL) GROUP BY loan_cases.id,
loan_cases.case_status ORDER BY loan_cases.rank ASC"
创建表定义
create_table "loan_applications", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "case_code"
end
create_table "loan_cases", force: :cascade do |t|
t.string "case_status", limit: 255
t.text "description"
t.text "can_flow_to"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
t.integer "rank"
end
create_table "case_statuses", force: :cascade do |t|
t.integer "loan_application_id"
t.integer "loan_case_id"
end
add_index "case_statuses", ["loan_application_id"], name: "index_case_statuses_on_loan_application_id", using: :btree
Rails模型
class LoanApplication
has_one :case_status, inverse_of: :loan_application, :dependent => :destroy
has_one :loan_case, :through => :case_status, :source => :loan_case
end
class CaseStatus
belongs_to :loan_application, inverse_of: :case_status
belongs_to :loan_case
end
class LoanCase
has_many :case_statuses
end
这在大约239ms内执行,但我相信它可以更短,并询问是否有任何方法可以更好地优化它?