【问题标题】:Slow postgres text column query缓慢的 postgres 文本列查询
【发布时间】:2014-09-06 09:14:41
【问题描述】:

我在包含状态标记的文本列上有一个 btree 索引 - 包含此字段的查询比没有它的查询运行速度慢 100 倍 - 我可以做些什么来加快它的速度?这是相当低的基数——我已经尝试过哈希、带有 text_pattern_ops 的 btree 和部分索引——排序规则是 utf8 。没有状态索引的查询几乎在同一时间运行...

db=# 显示 lc_collat​​e; lc_collat​​e ------------- en_US.UTF-8 (1 行) db=# 删除索引 job_status_idx; 删除索引 db=# CREATE INDEX job_status_idx ON job(status text_pattern_ops); 创建索引 db=# select status, count(*) from job group by 1; 状态 |数数 -------------+-------- 待定 | 365027 预订 | 37515 提交 | 20783 取消| 191707 谈判 | 30 完成| 241339 取消| 56 (7 行) db=#解释分析 SELECT key_ FROM "job" WHERE active = true and start > '2014-06-15T19:23:23.691670'::timestamp and status = 'completed' ORDER BY start DESC OFFSET 450 LIMIT 150; 查询计划 -------------------------------------------------- -------------------------------------------------- ---------------------------------------------- 限制(成本=5723.07..7630.61 行=150 宽度=51)(实际时间=634.978..638.086 行=150 循环=1) -> 在作业上使用 job_start_idx 向后索引扫描(成本=0.42..524054.39 行=41209 宽度=51)(实际时间=625.776..637.023 行=600 循环=1) Index Cond: (start > '2014-06-15 19:23:23.69167'::timestamp without time zone) 过滤器:(活动 AND(状态 = '完成'::文本)) 过滤器删除的行数:94866 总运行时间:638.358 毫秒 (6 行) db=#解释分析 SELECT key_ FROM "job" WHERE active = true 并开始 > '2014-06-15T19:23:23.691670'::timestamp ORDER BY start DESC OFFSET 450 LIMIT 150; 查询计划 -------------------------------------------------- -------------------------------------------------- ------------------------------------------ 限制(成本=1585.61..2114.01 行=150 宽度=51)(实际时间=4.620..6.333 行=150 循环=1) -> 在作业上使用 job_start_idx 向后索引扫描(成本=0.42..523679.58 行=148661 宽度=51)(实际时间=0.080..5.271 行=600 循环=1) Index Cond: (start > '2014-06-15 19:23:23.69167'::timestamp without time zone) 过滤器:激活 总运行时间:6.584 毫秒 (5 行)

【问题讨论】:

    标签: postgresql postgresql-9.3


    【解决方案1】:

    这是您的查询:

    SELECT key_
    FROM "job"
    WHERE active = true and
         start > '2014-06-15T19:23:23.691670'::timestamp and
         status = 'completed'
    ORDER BY start DESC
    OFFSET 450 LIMIT 150;
    

    status 上的索引不是很有选择性。我会建议一个综合指数:

    CREATE INDEX job_status_idx ON job(status text_pattern_ops, active, start, key_)
    

    这是一个覆盖索引,它应该更好地匹配where 子句。

    【讨论】:

    • 好的,所以这个索引工作得很好: CREATE INDEX job_start_status_idx ON job(start, status text_pattern_ops);关键是 start + status 有很好的选择性...现在运行大约 15ms。
    • 这很有趣。覆盖是重要的部分。它对whereorder by(大概)都使用start,这一定会节省大量时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 2017-07-30
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多