Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 在包含300个整数和300个字符(20)的表上插入失败_Postgresql_Npgsql - Fatal编程技术网

Postgresql 在包含300个整数和300个字符(20)的表上插入失败

Postgresql 在包含300个整数和300个字符(20)的表上插入失败,postgresql,npgsql,Postgresql,Npgsql,我已尝试测试TOAST功能并创建了代码: int length = 20; using (NpgsqlConnection conn = new NpgsqlConnection("")) { conn.Open(); StringBuilder ct = new StringBuilder(); ct.Append("CREATE TABLE t300 ("); for (int i = 0; i < 300; i

我已尝试测试TOAST功能并创建了代码:

int length = 20;
using (NpgsqlConnection conn = new NpgsqlConnection(""))
{
    conn.Open();

    StringBuilder ct = new StringBuilder();
    ct.Append("CREATE TABLE t300 (");
    for (int i = 0; i < 300; i++)
    {
        ct.Append("i").Append(i).Append(" int not null, n").Append(i).Append(" varchar(").Append(length).Append(") not null, ");
    }

    ct.Remove(ct.Length - 2, 2).Append(");");

    using (NpgsqlCommand cmd = new NpgsqlCommand(ct.ToString(), conn))
    {
        cmd.ExecuteNonQuery();
    }

    StringBuilder isql = new StringBuilder();
    isql.Append("INSERT INTO t300 (");
    StringBuilder vsql = new StringBuilder();
    vsql.Append("VALUES (");

    for (int i = 0; i < 300; i++)
    {
        isql.Append("i").Append(i).Append(", n").Append(i).Append(", ");
        vsql.Append(":i").Append(i).Append(", :n").Append(i).Append(", ");
    }

    isql.Remove(isql.Length - 2, 2).Append(") ").Append(vsql).Remove(isql.Length - 2, 2).Append(");");

    using (NpgsqlCommand cmd = new NpgsqlCommand(isql.ToString(), conn))
    {
        for (int i = 0; i < 300; i++)
        {
            cmd.Parameters.AddWithValue("i" + i.ToString(), NpgsqlDbType.Integer, i);
            cmd.Parameters.AddWithValue("n" + i.ToString(), NpgsqlDbType.Varchar, length, i.ToString() + new string('n', length - i.ToString().Length));
        }

        for (int i = 0; i < 10000; i++)
        {
            cmd.ExecuteNonQuery();
        }
    }
}

int-length=20;
使用(NpgsqlConnection conn=newNPGSQLConnection(“”)
{
conn.Open();
StringBuilder ct=新的StringBuilder();
ct.Append(“创建表t300(”);
对于(int i=0;i<300;i++)
{
ct.Append(“i”).Append(i).Append(“int-not-null,n”).Append(i).Append(“varchar(”).Append(length.Append(“)not-null,”);
}
删除(ct.Length-2,2)。追加(“);”;
使用(npgsqlcmd=newnpgsqlcommand(ct.ToString(),conn))
{
cmd.ExecuteNonQuery();
}
StringBuilder isql=新的StringBuilder();
isql.Append(“插入t300(”);
StringBuilder vsql=新的StringBuilder();
追加(“值(”);
对于(int i=0;i<300;i++)
{
isql.Append(“i”).Append(i).Append(“,n”).Append(i).Append(,”);
追加(“:i”).Append(i).Append(“,:n”).Append(i).Append(,”);
}
isql.Remove(isql.Length-2,2).Append(“)”.Append(vsql).Remove(isql.Length-2,2).Append(“);”;
使用(NpgsqlCommand cmd=newnpgsqlcommand(isql.ToString(),conn))
{
对于(int i=0;i<300;i++)
{
cmd.Parameters.AddWithValue(“i”+i.ToString(),NpgsqlDbType.Integer,i);
cmd.Parameters.AddWithValue(“n”+i.ToString(),NpgsqlDbType.Varchar,length,i.ToString()+新字符串('n',length-i.ToString().length));
}
对于(int i=0;i<10000;i++)
{
cmd.ExecuteNonQuery();
}
}
}
插入时此代码失败,异常为“54000,行大小(8424)超过限制(8160)”

当我将'length'变量设置为26时,代码运行良好。请告诉我消除这种情况的解决方法


Postgres 12,Npgsql 4.1.5

也许您对TOAST存储的工作原理有误解。PostgreSQL不会压缩整行并将其存储在TOAST表中,而是独立地将每一列压缩为不同长度的数据类型

因此,在toasting之后,该行仍然由600列组成,其中300列(整数)将不会被toasted(4字节),而其他300列(varchar)将包含toasted标头和TOAST指针

这两种情况加在一起恰好超过了单个块的大小,行的跨度不能超过单个块。这导致了错误


解决方案是不使用具有如此多列的表。您应该将数据拆分为几个表(规范化通常会解决这个问题)。如果一个实体确实有很多属性,那么这些属性很可能不会全部用于连接或
WHERE
条件。您可以考虑将这些属性存储在单个<代码> JSONB列中,其中烘烤将更加有效。

井8160是一个硬固定的限制,请参见。因此,没有现成的解决办法。正确的方法是规范化您的数据模型,将这个600列的怪物分解成多个表。然后创建一个视图(甚至对此不确定)。似乎只有一种解决方法可用。开源博士后。获取源代码,根据需要进行修改,重新编译并重新安装。您可能想知道为什么开发人员首先施加了这个限制。问问自己,这是否真的值得付出努力,是否具备必要的技能。