对于 PostgreSQL 表来说有多大?
Posted
技术标签:
【中文标题】对于 PostgreSQL 表来说有多大?【英文标题】:How big is too big for a PostgreSQL table? 【发布时间】:2014-03-18 22:26:24 【问题描述】:我正在为我的公司设计一个 RoR 项目,我们的开发团队已经就设计,特别是数据库进行了一些争论。
我们有一个名为Message
的模型需要持久化。这是一个非常非常小的模型,除了 id 之外只有三个 db 列,但是当我们投入生产时可能会有很多这些模型。我们每天看到多达 1,000,000 次插入。模型只会被它们上的两个可以索引的外键搜索。同样,模型永远不必删除,但我们也不必在它们大约三个月大后保留它们。
那么,我们想知道的是,在 Postgres 中实现这个表是否会带来严重的性能问题?有没有人有过非常大的 SQL 数据库的经验来告诉我们这是否会成为一个问题?如果是这样,我们应该选择什么替代方案?
【问题讨论】:
有一个很好的缓存层和 PG 中的一些小配置,你应该没问题。您应该逐个处理性能问题并避免预优化。也就是说,一旦遇到瓶颈,分区和复制始终是您可以利用的绝佳选择。 相关问题here和here。 我们在一个 5+ TB 的 PostgreSQL 数据库中每天处理大约 3000 万条消息,工作正常。 另见***.com/questions/3132444/… 仅供参考,我今天碰巧在阅读postgresql.org/about 并注意到它说(原则上)表中的行数是无限的。 【参考方案1】:每张桌子的行数本身不会成为问题。
粗略地说,每天 100 万行,持续 90 天就是 9000 万行。如果不知道您正在做什么的所有细节,我认为 Postgres 没有理由不能处理这个问题。
根据您的数据分布,您可以混合使用索引、过滤索引和某种类型的表分区,以便在您了解可能存在或不存在哪些性能问题后加快处理速度。在我知道的任何其他 RDMS 上,您的问题都将是相同的。如果您在一个过程中只需要 3 个月的数据设计来修剪您不再需要的数据。这样,您将在表上拥有一致的数据量。你很幸运,你知道会有多少数据存在,测试你的数量,看看你得到了什么。测试一个有 9000 万行的表可能很简单:
select x,1 as c2,2 as c3
from generate_series(1,90000000) x;
https://wiki.postgresql.org/wiki/FAQ
Limit Value
Maximum Database Size Unlimited
Maximum Table Size 32 TB
Maximum Row Size 1.6 TB
Maximum Field Size 1 GB
Maximum Rows per Table Unlimited
Maximum Columns per Table 250 - 1600 depending on column types
Maximum Indexes per Table Unlimited
【讨论】:
我同意 9000 万行对 PostgreSQL 来说不是问题。但这可能对于带有 PostgreSQL 的 ORM 来说是个问题。 (实际上是一个带有任何 dbms 的 ORM。) @yeyo:因为 ORM 通常使用大量查询来获取可以仅返回一两个的数据。 OP 正在使用 Ruby on Rails。 这有点晚了,但我认为在很多情况下(尤其是使用 rails / active record),通常会从等式中完全删除 ORM 并编写一个原始 sql 字符串来查询性能原因。不要让您的 ORM 为您做出数据决策!它是配件而非必需品。 URL 中引用的 about URL 目前没有显示这些限制 - 有人知道它移到了哪里吗? Rails/ActiveRecord 使用大量查询来获取只有一两个就可以返回的数据是不正确的。它完全能够在一两个查询中做同样的事情,但你必须实际告诉它这样做,而不是依赖默认行为。问题在于,由于它非常易于使用且如此抽象,许多查询都是由经验不足的人编写的,他们不一定了解这些事情,更不用说积极考虑它们了。这是使编程工具变得简单的普遍问题,而不是 ORM 或 Rails。【参考方案2】:在超过 1 亿行的表上显着加快查询的另一种方法是将表聚集在查询中最常用的索引上。在数据库的“关闭”时间执行此操作。我们有一个超过 2.18 亿行的表,并且发现了 30 倍的改进。
此外,对于非常大的表,最好在外键上创建索引。
示例:
-
假设我们在名为 ccbank 的数据库中有一个名为 investment 的表。
假设我们查询中最常用的索引是 (bankid,record_date)
以下是创建和聚集索引的步骤:
psql -c "drop index investment_bankid_rec_dt_idx;" ccbank
psql -c "create index investment_bankid_rec_dt_idx on investment(bankid, record_date);"
psql -c "cluster investment_bankid_rec_dt_idx on investment;"
vacuumdb -d ccbank -z -v -t investment
在步骤 1-2 中,我们将旧索引替换为新的优化索引。在第 3 步中,我们对表进行聚类:这基本上将 DB 表按索引的物理顺序排列,这样当 PostgreSQL 执行查询时,它会缓存最有可能的下一行。在第 4 步中,我们清理数据库以重置查询计划器的统计信息。
【讨论】:
> 在非工作时间将您查询中最常使用的索引上的表聚集在一起......您能解释一下这是如何完成的吗? 是的,这里是一步一步的例子: 1)我指的表在这个例子中叫做投资。 2)查询中使用最多的索引是(bankid,record_date)所以这里是你的一步一步:1)psql -c“drop indexinvestment_bankid_rec_dt_idx;” dbname 2) psql -c "创建索引investment_bankid_rec_dt_idx on investment(bankid, record_date);" 3) psql -c "cluster investment_bankid_rec_dt_idx on investment;" 4)vacuumdb -d ccbank -z -v -t investment 所以在第一步和第二步中,我们删除索引并重新创建它。 第 3 步我们创建集群,这基本上将 DB 表按索引的物理顺序放置,因此当 postgresql 执行查询时,它会缓存最有可能的下一行。第 4 步,我们清理数据库以重置查询计划器的统计信息以上是关于对于 PostgreSQL 表来说有多大?的主要内容,如果未能解决你的问题,请参考以下文章