我正在努力了解如何使用成本和实际时间来优化查询。我的应用是带有 PostgreSQL 9.1 db 的 rails 3。Delayed_job 使用我的查询:
EXPLAIN ANALYZE SELECT "delayed_jobs".*
FROM "delayed_jobs"
WHERE ((run_at <= '2011-05-23 15:16:43.180810' AND (locked_at IS NULL OR locked_at < '2011-01-25 11:05:28.077144') OR locked_by = 'host:foo pid:2') AND failed_at IS NULL AND queue = 'authentication_emails')
ORDER BY priority ASC, run_at ASC LIMIT 5
或者:
EXPLAIN ANALYZE SELECT "delayed_jobs".*
FROM "delayed_jobs"
WHERE ((run_at <= '2011-05-23 15:16:43.180810' AND (locked_at IS NULL OR locked_at < '2011-01-25 11:05:28.077144') OR locked_by = 'host:foo pid:2') AND failed_at IS NULL )
ORDER BY priority ASC, run_at ASC LIMIT 5
对于第一个查询,输出等于:
Limit (cost=7097.57..7097.57 rows=1 width=1008) (actual time=35.657..35.657 rows=0 loops=1)
-> Sort (cost=7097.57..7097.57 rows=1 width=1008) (actual time=35.655..35.655 rows=0 loops=1)
Sort Key: priority, run_at
Sort Method: quicksort Memory: 25kB
-> Seq Scan on delayed_jobs (cost=0.00..7097.56 rows=1 width=1008) (actual time=35.648..35.648 rows=0 loops=1)
Filter: ((failed_at IS NULL) AND ((queue)::text = 'authentication_emails'::text) AND (((run_at <= '2011-05-23 15:16:43.18081'::timestamp without time zone) AND ((locked_at IS NULL) OR (locked_at < '2011-01-25 11:05:28.077144'::timestamp without time zone))) OR (locked_by = 'host:foo pid:2'::text)))
Total runtime: 35.695 ms
该表目前有 90k 条记录,范围为 0-200k。我们注意到此查询导致 CPU 出现峰值并导致瓶颈。从上面的解释信息中可以学到什么。如果有索引,应该在哪里添加?谢谢
DB Schema.. 表有 0 个索引。
create_table "delayed_jobs", :force => true do |t|
t.integer "priority", :default => 0
t.integer "attempts", :default => 0
t.text "handler"
t.text "last_error"
t.datetime "run_at"
t.datetime "locked_at"
t.datetime "failed_at"
t.text "locked_by"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "queue"
end