Postgresql:text/varchar 的行内与行外

Postgresql: In-Row vs Out-of-Row for text/varchar

两部分问题:

  1. 什么是存储 text/varchars 行内 vs 的 Postgresql 行为 行外?我是否认为在默认设置下,所有列将始终存储在行中,直到达到 2kB 大小?

  2. 我们是否可以控制上述行为?有什么方法可以更改特定 column/table 的阈值,或强制特定列始终存储在行外?

我已通读 PostGresql Toast 文档 (http://www.postgresql.org/docs/8.3/static/storage-toast.html),但我没有看到任何更改阈值的选项(默认值似乎是 2kB 行)或强制列始终存储行外(EXTERNAL 仅允许,但不强制执行)。

我找到了说明如何在 SQL 服务器 (https://msdn.microsoft.com/en-us/library/ms173530.aspx) 上执行此操作的文档,但没有看到任何与 PostGresql 类似的内容。


如果有人对我的动机感兴趣,我有一个 table,它混合了短一致性列(ID、时间戳等),一个是 varchar(200) 的列,一个是text/varchar(max),长度可以非常大。我目前将两个 varchars 存储在单独的 table 中,只是为了在短一致列上实现高效 storage/lookups/scanning。

然而,这很痛苦,因为我经常需要进行连接才能读取所有数据。我真的很想将上述所有字段存储在同一个 table 中,并告诉 Postgresql 始终强制将 2 个 VARCHAR 存储在行外。

已编辑答案

对于问题的第一部分:您是正确的(例如参见 [​​=24=])。

对于问题的第二部分:存储列的标准方法是压缩可变长度的文本字段,如果它们的大小超过2KB,最后将它们存储到一个单独的区域,称为“TOAST table ”.

您可以通过对列使用以下命令向系统提供有关如何存储字段的“提示”:

ALTER TABLE YourTable
  ALTER COLUMN YourColumn SET STORAGE (PLAIN | EXTENDED | EXTERNAL | MAIN)

来自manual

SET STORAGE

This form sets the storage mode for a column. This controls whether this column is held inline or in a secondary TOAST table, and whether the data should be compressed or not. PLAIN must be used for fixed-length values such as integer and is inline, uncompressed. MAIN is for inline, compressible data. EXTERNAL is for external, uncompressed data, and EXTENDED is for external, compressed data. EXTENDED is the default for most data types that support non-PLAIN storage. Use of EXTERNAL will make substring operations on very large text and bytea values run faster, at the penalty of increased storage space. Note that SET STORAGE doesn't itself change anything in the table, it just sets the strategy to be pursued during future table updates. See Section 59.2 for more information.

由于手册在这一点上没有完全明确,这是我的解释:关于如何存储字段的最终决定在任何情况下都留给系统,给定以下限制:

  1. 无法存储任何字段以致超过一行的总大小 8KB
  2. 如果字段的大小小于 TOAST_TUPLE_THRESHOLD
  3. 满足前面的后 约束条件,系统会尝试满足 SET STORAGE 策略 由用户指定。如果没有指定存储策略,每个 TOAST-able 字段自动声明 EXTENDED.

在这些假设下,确保 所有 列的值都存储在行外的唯一方法是使用 [= 的值重新编译系统19=] 小于列的 any 值的最小大小。