PostgreSQL查询导致cpu峰值达到100%.给出90k记录,是7000的成本
我正在努力了解应如何使用成本和实际时间来优化查询.我的应用程序是带有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 解决方法
分析
如果您将转到this section of the PostgreSQL documentation,您将了解规划师如何使用统计数据来估算成本.这是非常有用的信息! 如果你说,那个表有90k的记录(并使用default costs),那么行处理的成本将是: 90000 * (cpu_tuple_cost + cpu_operator_cost) = 90000 * 0.0125 = 1125 我们现在可以估算您的表占用的页数: (7097.56-1125)/seq_page_cost = 5972.56 这使它大约46Mb(默认8k页面大小).因此,我假设您的表适合shared_buffers,甚至是默认表. 看一下平均行宽我也假设,该表是mostly stored as 接下来,您将使用text和string类型的字段作为谓词.不确定它们如何映射到PostgreSQL内部类型,但我认为它是文本.默认情况下,此类型是可压缩的,因此PostgreSQL必须对每一行执行解压缩以检查谓词.我不确定在哪个阈值压缩开始后,看看this message(和整个线程). 结论 >你还没有向我们展示真正的EXPLAIN(分析)输出,因为我也不认为35ms查询会导致瓶颈,除了…… 因此,我说瓶颈来自于数据并行运行的峰值查询量,这需要额外的CPU周期来进行解压缩. 该怎么办? >规范你的表格.感觉“队列”列的选择性非常低.考虑为它创建external type(如ENUM),或组织具有适当外键的字典表.我也不确定关键字是否被锁定,是否可以归一化? 我希望我在这里不是非常错误:)欢迎评论/更正! 附:让我知道它是怎么回事. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |