暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

提高 PostgreSQL 插入性能的 13 个技巧

其中一些可能会让您感到惊讶,但所有 13 种方法都将帮助您使用 PostgreSQL 和 TimescaleDB 提高INSERT性能 – 并看到与我们比较 TimescaleDB 性能与InfluxDB或MongoDB 的帖子中的消耗率。
INSERT性能对于许多常见的 PostgreSQL 用例至关重要,包括应用程序监控、应用程序分析、IoT 监控等。
虽然数据库长期以来都有时间字段,但这些用例收集的数据类型有一个关键区别:与标准的关系“业务”数据不同,更改被视为插入,而不是覆盖(换句话说,每个新值都成为一个新行在数据库中,而不是用最新的替换行的先前值)。
如果您在需要保留所有数据与覆盖过去值的场景中操作,那么优化数据库INSERT新数据的速度就变得至关重要。
 

提高PostgreSQL性能




 

以下是在 vanilla PostgreSQL 中提高性能的一些最佳实践:

 
1. 适度使用索引
拥有正确的索引可以加速您的查询,但它们不是灵丹妙药。增量维护每个新行的索引需要额外的工作。检查您在表上定义的索引数量(使用psql命令\d table_name),并确定它们潜在的查询好处是否超过存储和插入开销。由于每个系统都不同,因此没有任何硬性规定或索引的“神奇数字”——只要合理即可。
 
2. 重新考虑外键约束
有时需要从一个表到其他关系表构建外键 (FK)。当您有 FK 约束时,每个 INSERT 通常都需要从您引用的表中读取,这会降低性能。考虑一下是否可以对数据进行非规范化——我们有时会看到 FK 约束的极端使用,这是出于“优雅”的感觉而不是工程权衡。
 
3. 避免不必要的 UNIQUE 键
开发人员通常接受过在数据库表中指定主键的培训,许多 ORM 都喜欢它们。然而,许多用例——包括常见的监控或时间序列应用程序——并不需要它们,因为每个事件或传感器读取都可以通过在写入期间将其插入到超表当前块的尾部来简单地记录为一个单独的事件。
如果以其他方式定义了 UNIQUE 约束,则该插入可能需要进行索引查找以确定该行是否已存在,这将对 INSERT 的速度产生不利影响。
 
4. WAL 和数据使用单独的磁盘
虽然这是一种并不总是需要的更高级的优化,但如果您的磁盘成为瓶颈,您可以通过为数据库的预写日志 (WAL) 和数据使用单独的磁盘(表空间)来进一步提高吞吐量。
 
5. 使用高性能磁盘
有时,开发人员会将他们的数据库部署在磁盘速度较慢的环境中,无论是由于性能不佳的HDD、远程 SAN 还是其他类型的配置。并且因为在插入行时,数据会在事务完成之前持久存储到预写日志 (WAL),所以慢速磁盘会影响插入性能。要做的一件事是使用ioping命令检查您的磁盘IOPS 。
阅读测试:
$ ioping -q-c 10 -s 8k . --- . (hfs /dev/disk1 930.7 GiB) ioping statistics --- 9 requestscompleted in 208 us, 72 KiB read, 43.3 k iops, 338.0 MiB/s generated 10requests in 9.00 s, 80 KiB, 1 iops, 8.88 KiB/s min/avg/max/mdev = 18 us / 23.1us / 35 us / 6.17 us
 
写测试:
$ ioping -q-c 10 -s 8k -W . --- . (hfs /dev/disk1 930.7 GiB) ioping statistics --- 9requests completed in 10.8 ms, 72 KiB written, 830 iops, 6.49 MiB/s generated10 requests in 9.00 s, 80 KiB, 1 iops, 8.89 KiB/s min/avg/max/mdev = 99 us /1.20 ms / 2.23 ms / 919.3 us
 
您应该看到至少 1000秒的读取 IOPS 和许多 100 秒的写入 IOPS。如果您看到的数量少得多,则您的 INSERT 性能可能会受到磁盘硬件的影响。查看替代存储配置是否可行。
 

选择和配置TimescaleDB以获得更好的INSERT性能




 

TimescaleDB 进行了调整以提高摄取性能。TimescaleDB 最常见的用途包括为云基础设施指标、产品分析、Web 分析、物联网设备和许多其他时间序列用例存储大量数据。
与时间序列数据一样,这些场景以时间为中心,几乎完全是仅追加(大量插入),并且需要在小时间窗口内快速摄取大量数据。 
TimescaleDB 打包为 PostgreSQL 的扩展,专为时间序列用例而构建。因此,如果您的应用程序或系统需要从 PostgreSQL 中获得更快的摄取性能,请考虑使用 TimescaleDB(可通过Timescale Cloud 进行完全管理——我们的数据库即服务产品,或通过我们的免费社区版进行自我管理)。 
这里还有 8 种使用 TimescaleDB 提高摄取性能的技术:
 

1. 使用并行写入。

TimescaleDB 的每个 INSERT 或 COPY 命令(如在PostgreSQL 中)都作为单个事务执行,因此以单线程方式运行。为了实现更高的摄取,您应该并行执行多个INSERTS 或 COPY 命令。
 
有关并行批量加载大型CSV 文件的帮助,请查看 TimescaleDB 的并行复制命令。
 
⭐专业提示:确保您的客户端机器有足够的内核来执行这种并行性(在 2 个 vCPU 机器上运行 32 个客户端工作程序并没有太大帮助——工作程序实际上不会并行执行)。
 

2. 批量插入行。

为了获得更高的摄取率,您应该在每个 INSERT 调用中插入多行数据(或者使用一些批量插入命令,如 COPY 或我们的并行复制工具)。
 
不要逐行插入数据——而是尝试每次插入至少数百(或数千)行。这使得数据库可以在连接管理、事务开销、SQL 解析等方面花费更少的时间,而将更多的时间花在数据处理上。
 

3.正确配置shared_buffers

我们通常建议使用 25%的可用 RAM。如果您通过 run 的方法安装 TimescaleDB timescaledb-tune,它应该会自动配置shared_buffers为非常适合您的硬件规格的内容。
 
注意:在某些情况下,通常使用虚拟化和受限制的 cgroups 内存分配,这些自动配置的设置可能并不理想。要检查您shared_buffers的设置是否在 25% 范围内,请SHOW shared_buffers从您的psql连接运行。
 

4. 在 Linux 主机上运行我们的 Docker 镜像

如果您在另一个Linux 操作系统之上运行 TimescaleDB Docker 容器(运行 Linux),那么您的状态很好。容器基本提供进程隔离,开销极小。
 
如果您在 Mac 或 Windows 机器上运行容器,您会看到操作系统虚拟化的一些性能下降,包括 I/O。
 
相反,如果您需要在Mac 或 Windows 上运行,我们建议直接安装而不是使用Docker 映像。
 

5. 以松散的时间顺序写入数据

当块的大小合适时(参见#11和#12),最新的块及其相关索引自然会保存在内存中。插入有最近时间戳的新行将被写入内存中已经存在的这些块和索引。
 
如果插入具有足够旧时间戳的行(即,它是乱序或回填写入),则需要从磁盘读入与旧块(及其索引)对应的磁盘页面。这将显着增加写入延迟并降低插入吞吐量。
 
特别是,当您第一次加载数据时,请尝试按排序后的时间戳顺序加载数据。
 
如果您要批量加载有关许多不同服务器、设备等的数据,请小心:
 
不要按服务器顺序批量插入数据(即,服务器 A 的所有数据,然后是服务器 B,然后是 C,依此类推)。这将导致磁盘抖动,因为加载每个服务器将在重新开始之前遍历所有块。
相反,安排批量加载,以便所有服务器的数据以宽松的时间戳顺序插入(例如,并行跨所有服务器的第 1 天,然后并行跨所有服务器的第 2 天,等等)
 

6. 避免“太大”的块

为了保持更高的摄取率,您希望最新的块及其所有相关索引留在内存中,以便写入块和索引更新仅更新内存。(写入仍然是持久的,因为在更新数据库页面之前将插入写入磁盘上的 WAL。)
 
如果您的块太大,那么即使是最新的块的写入也将开始交换到磁盘。
 
根据经验,我们建议将最新的块及其所有索引轻松放入数据库的shared_buffers. 您可以通过chunk_relation_size_pretty命令检查块大小。
=> SELECTchunk_table, table_size, index_size, toast_size, total_sizeFROMchunk_relation_size_pretty('hypertable_name')ORDER BY ranges DESC LIMIT 4;chunk_table               | table_size |index_size | toast_size | total_size-----------------------------------------+------------+------------+------------+------------_timescaledb_internal._hyper_1_96_chunk | 200 MB     | 64 MB      | 8192 bytes | 272 MB_timescaledb_internal._hyper_1_95_chunk | 388 MB     | 108 MB     | 8192 bytes | 500 MB_timescaledb_internal._hyper_1_94_chunk | 388 MB     | 108 MB     | 8192 bytes | 500 MB_timescaledb_internal._hyper_1_93_chunk | 388 MB     | 108 MB     | 8192 bytes | 500 MB
 
如果您的块太大,您可以通过set_chunk_time_interval命令更新未来块的范围。然而,这不会修改现有块的范围(例如,通过将大块重写为多个小块)。
 
对于单个块远大于可用内存的配置,我们建议将您的 hypertable 数据转储并重新加载到适当大小的块。
 
保持最新的块适用于所有活动的超表;如果您正在主动写入两个超级表,则两者的最新块应该适合shared_buffers.
 

7. 避免太多或太小的块

除非您正在运行多节点TimescaleDB,否则我们目前不建议使用空间分区。如果你这样做了,请记住这个数量的块是为每个时间间隔创建的。
 
因此,如果您创建 64 个空间分区和每日数据块,那么每年您将拥有 24,640 个数据块。与插入时间相比,这可能会导致查询时间(由于计划开销)更大的性能损失,但仍然需要考虑一些问题。另一件要避免的事情是:在指定时间间隔范围时使用不正确的整数值create_hypertable。
 
⭐专业提示:
 
如果您的时间列使用本机时间戳类型,则任何整数值都应以微秒为单位(因此一天 = 86400000000)。我们建议使用间隔类型(“1 天”)以避免任何混淆的可能性。
如果您的时间列是整数或bigint 本身,请使用适当的范围:如果整数时间戳以秒为单位,请使用 86400;如果 bigint 时间戳以纳秒为单位,请使用 86400000000000。
 
在这两种情况下,您都可以使用chunk_relation_size_pretty来确保您的块大小或分区范围看起来合理:
=> SELECTchunk_table, ranges, total_size FROMchunk_relation_size_pretty('hypertable_name') ORDER BY ranges DESC LIMIT 4;chunk_table               |                         ranges                          | total_size-----------------------------------------+---------------------------------------------------------+------------_timescaledb_internal._hyper_1_96_chunk | {"['2020-02-1323:00:00+00','2020-02-14 00:00:00+00')"} | 272 MB_timescaledb_internal._hyper_1_95_chunk | {"['2020-02-1322:00:00+00','2020-02-13 23:00:00+00')"} | 500 MB_timescaledb_internal._hyper_1_94_chunk | {"['2020-02-1321:30:00+00','2020-02-13 22:00:00+00')"} | 500 MB _timescaledb_internal._hyper_1_93_chunk| {"['2020-02-13 20:00:00+00','2020-02-13 21:00:00+00')"} | 500 MB     
   

8.Watch 行宽

插入宽行(例如 50、100、250 列)的开销将远高于插入窄行(更多网络 I/O、更多解析和数据处理、更大的 WAL 写入等)。我们发布的大多数基准测试都使用TSBS,每行使用 12 列。因此,如果您的行非常宽,您将相应地看到较低的插入率。
 
如果您正在考虑非常宽的行,因为您有不同类型的记录,并且每种类型都有一组不相交的列,您可能想要尝试使用多个超表(每个记录类型一个)——特别是如果您不经常查询这些类型。
 
此外,如果几乎所有列都是稀疏的,JSONB 记录是另一个不错的选择。也就是说,如果您使用的是稀疏宽行,请尽可能对缺失的记录使用 NULL,而不是默认值,以获得最大的性能提升(NULL 的存储和查询成本要低得多)。
 
最后,一旦您使用TimescaleDB的本机压缩压缩行,宽行的成本实际上要低得多。行被转换为更多的列压缩形式,稀疏列压缩得非常好,并且对于不获取单个列的查询,不会从磁盘读取压缩列。
 
 

概括




 


如果摄取性能对您的用例至关重要,请考虑使用 TimescaleDB。您可以立即免费开始使用 Timescale Cloud,也可以免费将 TimescaleDB 下载到您自己的机器或云实例。
 
我们的支持方法是解决您的整个解决方案,因此我们在这里帮助您实现所需的性能结果(请参阅有关我们的客户服务团队和精神的更多详细信息)。


PG考试咨询

往期回顾

永远都不晚:PostgreSQL认证专家(培训考试-广州站)

PGCCC,公众号:PostgreSQL考试认证中心永远都不晚:PostgreSQL认证专家(培训考试-广州站)

PostgreSQL-PCP认证专家-上海站、广州站

PGCCC,公众号:PostgreSQL考试认证中心开班通知-PCP认证专家(上海站)培训开班1106

PostgreSQL-PCP认证专家-北京站-精彩花絮

PGCCC,公众号:PostgreSQL考试认证中心PostgreSQL认证专家考试(培训)(10月16日北京站)精彩花絮

PostgreSQL-PCP认证专家-成都站

公众号:PostgreSQL考试认证中心开班通知-PCP认证专家(成都站)培训开班1016

PostgreSQL-PCP认证专家考试-北京站-考试风采

PGCCC,公众号:PostgreSQL考试认证中心PostgreSQL认证专家考试(培训)-北京站-成功举办

PostgreSQL-PCA认证考试-贵阳站-考试风采

PGCCC,公众号:PostgreSQL考试认证中心PostgreSQL PCA+PCP认证考试在贵阳成功举办

PostgreSQL-PCP认证专家考试-上海站-考试风采

PGCCC,公众号:PostgreSQL考试认证中心PostgreSQL PCP认证考试(上海站)成功举办

PostgreSQL认证专家考试-学员考试总结

薛晓刚,公众号:PostgreSQL考试认证中心难考的PostgreSQL认证考试

PostgreSQL-PCM认证大师考试-天津站-考试风采

PGCCC,公众号:PostgreSQL考试认证中心PostgreSQL-PCM认证大师考试(天津站)成功举办

如何在工业和信息化部教育与考试中心官网查询证书

PG考试认证中心,公众号:PostgreSQL考试认证中心如何在工业和信息化部教育与考试中心查询PostgreSQL证书

中国PostgreSQL考试认证体系

PG考试认证中心,公众号:PostgreSQL考试认证中心中国PostgreSQL考试认证体系


文章转载自PostgreSQL考试认证中心,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论