【问题标题】:How to organize primary keys for good locality?如何为良好的局部性组织主键?
【发布时间】:2013-11-10 19:28:48
【问题描述】:

我有一个用户表和一个文档表。文档只有一个用户作为所有者,对于我正在构建的应用程序,我知道我通常会访问与单个给定用户关联的一组文档。

假设普通用户有 K 个文档,某些常见查询会获取给定用户的所有文档。我不希望我的数据库(PostgreSQL)必须进行 K 磁盘搜索(平均而言)来获取用户的所有文档。理想情况下,文档将存储在连续的块中,以便提取只需要几次搜索。

是否有可能(并且合理)组织文档表模式来创建这样的位置?我知道无 SQL 实现总是这样做吗?例如。 BigTable paper 讨论了如何通过 URL 分配 web 表的行键,除了 url 是颠倒的,例如com.cnn.www,以便 CNN 的所有页面在数据存储中彼此靠近。在 Postgres 中似乎不可能有类似的东西,因为这些表不能被索引组织,尽管在带有 InnoDB 的 MySQL 中可能是可能的。 This post 得出了类似的结论。

【问题讨论】:

标签: sql postgresql primary-key database-schema composite-primary-key


【解决方案1】:

您要查找的命令是CLUSTER,但它有缺点。当您运行它时,它会完全重写表,这需要对其进行锁定,因此您可能只想在流量较低时执行此操作。此外,Postgres 不会在 INSERT 和 UPDATE 期间保持行的顺序,因此您的数据会随着表的写入而产生碎片,您可能必须定期重新聚集它。

您还可以在表上设置一个较低的填充因子,以便更新更有可能将给定行保留在同一页面上。这应该可以防止一些碎片,这些碎片只会留下 INSERT,但填充因子较低的 INSERT 往往会放置在较新的页面上,并且这些页面可能会经常被访问到足以保存在 RAM 中。我正在对您的使用模式做出假设,这可能是错误的,但无论如何,您最好的做法可能是在看到 I/O 开始成为问题时重新集群。

最后,还有一个名为pg_repack 的工具可以在不占用如此重锁的情况下对表进行集群,其方式类似于 CREATE INDEX CONCURRENTLY 的工作方式,但它是第三方工具,因此您需要在投入生产之前进行试验。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-12
    • 1970-01-01
    • 2020-10-06
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    相关资源
    最近更新 更多