3.6. 应用程序开发

3.6.1. 数据类型
3.6.2. 序列
3.6.3. 参考资料

3.6.1. 数据类型

数值类型

  • 对于精确计算和/或具有许多位数的数字,请选择 numeric 类型。

  • 对于较小的存储空间和更快的计算,请选择整数类型(smallint, int, bigint)和浮点类型(real, double precision, float)。

  • decimal 类型是 numeric 的别名。ltsql 的 \d 和 lt_dump 输出会将 decimal 列显示为 numeric 而不是 decimal。

时间戳

  • timestamp without time zone 忽略 TimeZone 参数。值按原样存储和返回。

  • timestamp with time zone 尊重输入值中显式的时区或 TimeZone 参数。输入值转换为 UTC,输出值根据生效的时区从存储的值转换。

二进制

  • 可用于存储二进制数据的方法

    • bytea 数据类型

    • 大对象:使用类似文件系统的打开/关闭/读取/写入接口,数据存储在 pg_largeobject 中,用户表列包含指向 pg_largeobject 中的一行的 OID 值。

    • 外部文件:应用程序管理文件系统或对象存储中的数据,并在表字符列中存储文件路径。

  • 如何选择:

    • 需要事务性(ACID)属性? -> bytea, 大对象

    • 处理 1 GB 或更大的列值? -> 大对象, 外部文件

    • 需要随机和/或部分访问? -> 大对象, 外部文件

    • 是否希望在处理 100 MB 或更大的列值时获得最佳性能? -> 外部文件

使用大对象的提示

  • 不要使用大对象。 它们可能会有问题。使用 bytea 列或外部文件存储如操作系统文件系统和对象存储。

  • 删除大量 LOB

    • 尝试在一个事务内删除许多大对象,例如, "SELECT lo_unlink(lo_oid) FROM mytable;" 可能会失败,并显示以下消息:

      • ERROR: out of shared memory

      • HINT: You might need to increase max_locks_per_transaction.

    • 原因:当删除一个大对象时,它被锁定为 Access Exclusive 模式。因此,需要与已删除的 LOB 数目相等的条目存在于锁表中。

    • 解决方案:可以做以下任一或两者:

      • 增加 max_locks_per_transaction。必须重启数据库服务器。

      • 分批删除 LOB,例如,每笔事务删除 100 个 LOB。

3.6.2. 序列

没有无间隙的序列

  • 当以下情况发生时,序列会产生间隙:

    • 事务回滚:因为 nextval() 和 setval() 的调用永远不会被回滚,所以分配的序列值不会被重新获取。

    • 缓存的值未被使用:如果为序列启用了缓存,nextval() 会预先分配指定数量的值并将它们缓存在会话的本地内存中。随后的 nextval() 调用将从缓存中获取值,直到缓存为空,然后再次预分配一些值。因此,如果会话结束而没有使用所有缓存的值,那么这些值将成为间隙。

    • 服务器崩溃:即使对于 NO CACHE 序列,在以下步骤中也会看到间隙:nextval() -> 崩溃恢复 -> nextval()。为了性能考虑,Lightdb 并不会对每次从序列中获取的值进行 WAL 日志记录。nextval() 会对当前值前 32 个数的位置的日志进行 WAL 记录,并且接下来的 32 次 nextval() 调用不会记录任何 WAL 日志。结果是,有些数字看起来像是跳过了。

3.6.3. 参考资料

Lightdb 文档