我有一个用户表和一个文档表。文档只有一个用户作为所有者,对于我正在构建的应用程序,我知道我通常将访问与单个给定用户关联的一组文档。
假设一个普通用户有K个文档,而某些常见查询会获取给定用户的所有文档。我不希望我的数据库(PostgreSQL)必须执行K disk seeks(平均)来为用户获取所有文档。理想情况下,文档将存储在连续的块中,因此获取只需要几个seek。
组织文档表架构来创建这样的位置是否可能(而且合理)?我知道没有一个SQL实现会一直这样做?例如,BigTable paper讨论如何通过URL分配web表的行键,除了URL是反向的,例如com.cnn.www,这样cnn的所有页面都位于数据存储区中的每个节点附近。虽然在MySQL w/InnoDB中是可能的,但在Postgres中似乎不可能出现类似的情况,因为表不能被索引组织。This post得出了类似的结论。
最佳答案
您要查找的命令是CLUSTER,但它有缺点。当您运行表时,它会完全重写该表,这需要对其进行锁定,因此您可能只想在流量较低时执行此操作。此外,在插入和更新过程中,Postgres不会按顺序保存行,因此在向其写入表时,您的数据将趋向于碎片化,您可能需要定期对其重新排序。
您还可以在表上设置一个较低的填充因子,以便更新更可能将给定的行保留在同一页上。这应该可以防止一些碎片,这些碎片只会留下插入,但是由于填充因子较低,插入将倾向于放在较新的页面上,并且这些页可能通常被访问到足以保存在RAM中。我正在假设您的使用模式可能是错误的,但是不管怎样,只要您看到I/O开始成为一个问题,您最好的做法可能就是重新调整。
最后,还有一个名为pg_repack的工具,它可以在不带这么重锁的情况下对表进行集群,其方式与CREATE INDEX并发工作的方式类似,但它是第三方工具,因此您需要在生产环境中运行之前对其进行试验。
关于sql - 如何组织主键以获得良好的位置?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19695553/