Directus地图字段由于B-Tree索引错误无法保存

字段Geo是一个地图类型的,使用了Postgresql数据库,保存的时候出错

{
  "message": "update \"records\" set \"geo\" = st_geomfromtext($1, 4326), \"title\" = $2, \"slug\" = $3, \"author\" = $4, \"meta\" = $5, \"user_updated\" = $6, \"date_updated\" = $7 where \"id\" in ($8) - index row size 4600 exceeds btree version 4 maximum 2704 for index \"records_geo_index\"",
  "extensions": {
    "code": "INTERNAL_SERVER_ERROR"
  }
}

原因分析

  • B-Tree 索引限制:B-Tree 索引的单个索引条目不能超过 1/3 的页面大小(默认页面大小为 8KB,即单个条目限制为 ~2704 字节)。
  • 几何数据大小问题:如果 geo 列的几何数据非常复杂(例如多边形或多线段,包含大量顶点),它可能会导致索引条目大小超出限制。

该错误表明表 records 中的索引 records_geo_index 出现了问题,具体是由于索引的行大小超过了 B-Tree 索引允许的最大大小(2704 字节)。这是 PostgreSQL 的限制之一。

解决方案

使用 GiST 或 SP-GiST 索引替代 B-Tree

PostGIS 提供了专门用于空间数据的索引类型(如 GiST 和 SP-GiST),它们不会受到 B-Tree 索引行大小的限制。

重新创建索引为 GiST 索引:

DROP INDEX IF EXISTS records_geo_index;

CREATE INDEX records_geo_index ON records USING gist(geo);

或者,如果你的数据主要是点类型并且分布均匀,也可以使用 SP-GiST:

DROP INDEX IF EXISTS records_geo_index;

CREATE INDEX records_geo_index ON records USING spgist(geo);

检查和重建表数据

如果表已经有大量复杂的空间数据,索引可能已经损坏或受到影响,可以尝试以下步骤:

DROP INDEX IF EXISTS records_geo_index;

清理表和统计信息:

VACUUM FULL records;
ANALYZE records;

Post Comment