del*_*rox 7 postgresql indexing
对不起,在实际问题之前有很多上下文,因为我们已经仔细研究了这个,我想给你完整的背景.
某些上下文:postgres仅索引扫描依赖于可见性映射(VM).如果页面未在可见性映射中标记为不完全可见,则postgres将获取该页面以确保此事务对数据可见,即使仅执行索引扫描也是如此.不幸的是,这可以大大减慢索引只扫描.索引可能会返回10k行的结果,但索引本身只能跨越50页(就IO而言非常快).但是,如果未设置VM,则会进行额外的10k堆提取(在IO方面减慢200倍).
详细信息:https://wiki.postgresql.org/wiki/Index-only_scans#The_Visibility_Map_.28and_other_relation_forks.29
自己试试:在VACUUM之前和之后,EXPLAIN ANALYZE仅索引查询.您可以在VACUUM之后看到堆提取的数量下降(假设您之前在VM中有一些脏页)
已经尝试过:我们已经调整了autovacuum,我们经常吸尘.这有很大帮助,但我们想要更快.
问题(最后):在进行仅索引扫描时是否可以跳过堆取?我知道在阅读时我们不会有完美的MVCC,但我们对此感到满意.索引中的数据足够接近,绝对不值得数千个堆提取的开销,以确保我们不会查看稍微陈旧的数据.借用NoSQL中的一个术语,我们可以完成"最终一致性"读取.
谢谢!
在 PostgreSQL 中,没有办法做你想做的事。做一些工作会很有趣,但不太可能被核心接受,扩展起来非常困难,并且可能会产生比您预期更糟糕的副作用。
基本上,您必须DIRTY READ向 PostgreSQL 添加隔离级别,但它会比隔离级别更弱,因为它还可能返回已删除的数据、更新行的旧版本以及唯一索引中的多个值。后一个问题可能会让查询规划器感到相当不安,因为它可以假设唯一索引的结果是唯一的。
我认为这样的更改被 PostgreSQL 核心接受的可能性非常接近于零。可能的用例非常有限。
我认为添加此类功能的唯一方法是通过支持原始读取来更轻松地从阻塞丢失/损坏和意外删除中恢复。这对于堆的 seqscans 而不是仅索引扫描最有意义。
以另一种方式解决这个问题可能更有意义,例如在数据库之上为不需要完全新鲜的数据设置非持久缓存层(Redis 等)。