加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

PostgreSQL查询导致cpu峰值达到100%.给出90k记录,是7000的成本

发布时间:2020-12-13 16:07:51 所属栏目:百科 来源:网络整理
导读:我正在努力了解应如何使用成本和实际时间来优化查询.我的应用程序是带有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_a
我正在努力了解应如何使用成本和实际时间来优化查询.我的应用程序是带有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 MAIN.

接下来,您将使用text和string类型的字段作为谓词.不确定它们如何映射到PostgreSQL内部类型,但我认为它是文本.默认情况下,此类型是可压缩的,因此PostgreSQL必须对每一行执行解压缩以检查谓词.我不确定在哪个阈值压缩开始后,看看this message(和整个线程).

结论

>你还没有向我们展示真正的EXPLAIN(分析)输出,因为我也不认为35ms查询会导致瓶颈,除了……
>您还没有提到在瓶颈时刻有多少会话正在使用您的数据库,而且还不清楚此查询的运行频率.我认为它非常受欢迎.
>您的表似乎适合内存,因此在任何情况下所有操作都将受CPU限制.
>谓词中使用的值是可压缩的,似乎是压缩的.

因此,我说瓶颈来自于数据并行运行的峰值查询量,这需要额外的CPU周期来进行解压缩.

该怎么办?

>规范你的表格.感觉“队列”列的选择性非常低.考虑为它创建external type(如ENUM),或组织具有适当外键的字典表.我也不确定关键字是否被锁定,是否可以归一化?
>在run_at和locked_at列上创建索引.
>索引ON优先级,run_at列将使您的排序受益,但我怀疑它在这种情况下会有所帮助.我假设优先级列的选择性较低,因此规划者更喜欢在run_at和locked_at列上使用Bitmap和Index Scans.

我希望我在这里不是非常错误:)欢迎评论/更正!

附:让我知道它是怎么回事.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读