gpt4 book ai didi

performance - 如何在 PostgreSQL 中快速插入 BLOB?

转载 作者:行者123 更新时间:2023-11-29 11:53:29 25 4
gpt4 key购买 nike

您对配置 PostgreSQL 以快速编写 BLOB 有何建议?

我们正在使用 PostgreSQL 以高速率插入 BLOB。

  1. 我们大约每秒调用 lo_write() 220 次。
  2. 我们每次 lo_write() 写入大约 30KB 的二进制数据。
  3. 这相当于大约 6 MB/s。

我们的计算机是 RAID-5,因此写入速度在 200 MB/s 左右。

我们已经将 postgresql.conf 调整为具有以下内容:

  1. 我们更改了 shared_buffers = 1GB
  2. 我们关闭了 fsync
  3. logging_collector = off(几乎所有与日志相关的东西都关闭)

我们已经确保,如果我们不将 BLOB 存储为我们的 INSERT 查询的一部分,那么 PgSql 会保持良好状态。只有当我们将 BLOB 存储为查询的一部分时,它才会变慢。

编辑:我使用的是 Windows XP/Server。我将 Pgsql 8.3 与 PostGIS 1.3.6 一起使用。我需要将 BLOB 存储在数据库中的原因是因为我的应用程序需要我实时搜索这些 BLOB。

背景:我们的应用是高性能实时信号处理,我们将信号作为 BLOB 存储到数据库中。

编辑:这是我们用来执行基准测试的 C++ 代码。显然,我们的 RAID 配置速度大约为 16 MB/s。

#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include <sstream>
#include <iostream>
#include <tbb/tick_count.h>

void test()
{
std::stringstream stst;
stst << "user=postgres password=1234 dbname=test_db";
PGconn* conn = PQconnectdb(stst.str().c_str());
if (PQstatus(conn) != CONNECTION_OK)
{
throw std::exception("failed to connect To DB engine: ");
}

const int dataSize = 18512;
char* data = (char*) malloc( dataSize );


const int count = 10000;

tbb::tick_count t0 = tbb::tick_count::now();
for( int idx = 0; idx < count; idx++ )
{
// Insert acoustic binary into large object table "pg_largeobject"
Oid objectId;
int lobj_fd;
PGresult *res;

res = PQexec(conn, "begin");
PQclear(res);

objectId = lo_creat(conn, INV_READ|INV_WRITE);
if (objectId == 0)
{
throw std::exception("AddAcousticTable: Cannot create large object\n");
}

lobj_fd = lo_open(conn, objectId, INV_WRITE);

const unsigned int writeBytes = lo_write(conn, lobj_fd, data, dataSize );
if (writeBytes != dataSize )
{
std::stringstream msg;
msg << "PsSasDataDB::AddToAcousticTable(): Incorrect number of bytes written for large object ";
msg << writeBytes;
throw std::exception(msg.str().c_str());
}

lo_close(conn, lobj_fd);

res = PQexec(conn, "end");
PQclear(res);
}
tbb::tick_count t1 = tbb::tick_count::now();

std::cout << "Performance: " << (double(count*dataSize)/(t1-t0).seconds())/(1024.0*1024.0) << " MB/seconds";

free( data );
}
int main()
{
try
{
test();
}
catch( std::exception e )
{
std::cerr << e.what();
}

return 0;
}

最佳答案

RAID5:

它非常适合读取、写入大量大数据和降低成本。对于小的随机写入来说很糟糕。

由于您可能不使用您的数据库来仅存储大 blob,您还进行一些数据库写入/更新/插入,RAID5 将成为真正的 PITA。

  • 您在表中插入或更新一行。-> 表格中的一页需要写入-> 对于每个索引,至少需要更新一个索引页-> 在提交时,需要写入日志、刷新到磁盘并同步。

这些小的 1 页 (8kB) 写入中的每一个都小于您的 RAID5 strip 大小,因此 RAID Controller 将需要寻找几个(或所有)您的 RAID 磁盘,读取多个 strip ,然后重新写入更新的 strip 和平价。对于同步,您必须等待所有磁盘同步,在此期间它们不为任何其他请求提供服务……一些 RAID Controller 在执行此速度方面也特别糟糕,这取决于您的硬件。

-> 对于高随机写入吞吐量,最好对数据使用 RAID 1(或 10 或 01),并在 2 个单独的磁盘上为日志使用额外的 RAID1 卷。

因此,如果您的 RAID5 中有 3 个磁盘,请移除一个,将数据放在磁盘上并在另一个磁盘上登录,然后进行基准测试。如果好的话,再多加一 block 盘,做2个RAID1卷(日志,数据)。

如果您的负载是重读而不是重写,对于相同的预算(磁盘数量),最好将日志放在与数据相同的卷上,并且全部采用 RAID10。


The reason why I needed to store BLOB in the DB is because my application requires me to search for these BLOBs in real-time.

如果你想使用数据库擅长的东西(比如事务、安全性,或者把所有东西都放在一台服务器上,从任何地方都可用,连贯的备份,没有麻烦,等等),你可以把 BLOB 放在数据库中。

如果您想进行搜索,您不是使用 BLOB 进行搜索,而是使用简单的数据库表和 SQL 查询来获取对所需 BLOB 的引用。然后,您将获得 BLOB,但您也可以轻松地获得一个文件系统文件。因此,在您的应用程序中,您也可以改用文件系统文件,这样会快很多。

关于performance - 如何在 PostgreSQL 中快速插入 BLOB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1174848/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com