启用 PostGIS 的 Postgres DB JDBC 查询卡在 SQLException.setNextException
PostGIS-enabled Postgres DB JDBC Query Stuck in SQLException.setNextException
我目前是 运行 具有以下版本字符串的启用 PostGIS 的 Postgres 数据库:
Version string PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-16), 64-bit
我用来连接的 JDBC 驱动程序是
9.4-1201-jdbc41
我是运行以下查询:
SELECT * FROM foo;
'foo' 的架构如下:
CREATE TABLE foo
(
gid integer NOT NULL DEFAULT nextval('address_gid_seq'::regclass),
objectid numeric(10,0),
house_num integer,
half_add character varying(4),
pre_dir character varying(2),
st_name character varying(50),
st_type character varying(4),
suf_dir character varying(2),
unit_type character varying(4),
unit_id character varying(6),
city character varying(15),
state character varying(2),
zipcode numeric(10,0),
angle numeric,
parcel_num character varying(11),
idnum numeric(10,0),
status character varying(1),
status_dat date,
esnnum character varying(5),
geom geometry(Point,3857),
CONSTRAINT address_pkey PRIMARY KEY (gid)
)
我没有创建这个 table,所以我不确定可能出了什么问题,但行数(使用 pgAdmin3 作为快捷方式完成)约为 250,000,因此有明显的数据在那里。要求通过 'limit' 获取一些数据是可行的,尽管它非常慢。
我可以在调试器中暂停我的查询,它会在以下堆栈中暂停:
PSQLWarning(SQLException).setNextException(SQLException) line: 294
PSQLWarning(SQLWarning).setNextWarning(SQLWarning) line: 213
Jdbc4ResultSet(AbstractJdbc2ResultSet).addWarning(SQLWarning) line: 2669
AbstractJdbc2ResultSet$CursorResultHandler.handleWarning(SQLWarning) line: 1841
QueryExecutorImpl.handleWarning(SQLWarning) line: 2179
QueryExecutorImpl.processResults(ResultHandler, int) line: 2023
QueryExecutorImpl.fetch(ResultCursor, ResultHandler, int) line: 2201
Jdbc4ResultSet(AbstractJdbc2ResultSet).next() line: 1924
我真的没有太多时间来了解 Postgres 的 JDBC 驱动程序是如何实现的,所以我想我大声疾呼,看看是否有其他人经历过这种情况,是否有什么问题table 中的数据有误。如果我可以访问源数据,我也许可以在那一端修复它;但是针对现有 Postgres table 的查询会导致似乎是无限循环,这似乎很奇怪。
我应该补充一点,ResultSet.next() 永远不会进入调试器,代码只是无限期地停留在 setNextException() 方法中。
编辑:
我在 pgAdmin 的 "messages" 中得到了很多这样的东西:
NOTICE: [g_serialized.c:gserialized_get_type:50] entered
NOTICE: [lwgeom.c:lwgeom_set_srid:1455] entered with srid=3857
NOTICE: [lwgeom.c:lwgeom_is_empty:1233] lwgeom_is_empty: got type Point
NOTICE: [lwout_wkb.c:lwgeom_to_wkb:710] WKB output size: 25
NOTICE: [lwout_wkb.c:lwgeom_to_wkb:723] Hex WKB output size: 51
NOTICE: [lwgeom.c:lwgeom_is_empty:1233] lwgeom_is_empty: got type Point
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:393] Entering function, buf = 0x2acec3c3e770
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:395] Endian set, buf = 0x2acec3c3e772
NOTICE: [lwout_wkb.c:integer_to_wkb_buf:189] Writing value '536870913'
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:398] Type set, buf = 0x2acec3c3e77a
NOTICE: [lwout_wkb.c:integer_to_wkb_buf:189] Writing value '3857'
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:403] SRID set, buf = 0x2acec3c3e782
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:360] Writing point #0
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:364] Writing dimension #0 (buf = 0x2acec3c3e782)
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:364] Writing dimension #1 (buf = 0x2acec3c3e792)
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:369] Done (buf = 0x2acec3c3e7a2)
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:407] Pointarray set, buf = 0x2acec3c3e7a2
NOTICE: [lwout_wkb.c:lwgeom_to_wkb:759] buf (0x2acec3c3e7a3) - wkb_out (0x2acec3c3e770) = 51
NOTICE: [g_serialized.c:gserialized_get_type:50] entered
NOTICE: [g_serialized.c:lwgeom_from_gserialized:1137] Got type 1 (Point), srid=3857
NOTICE: [g_serialized.c:lwgeom_from_gserialized_buffer:1091] Got type 1 (Point), hasz=0 hasm=0 geodetic=0 hasbox=0
client_min_messages
未显示任何设置。
这个问题的解决方法如评论所述:
将 client_min_messages
设置为 ERROR
。这将避免在每个几何记录 JDBC 上向客户端发送十几个错误消息,在我的例子中,这将至少提高一个数量级的性能。
我目前是 运行 具有以下版本字符串的启用 PostGIS 的 Postgres 数据库:
Version string PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-16), 64-bit
我用来连接的 JDBC 驱动程序是
9.4-1201-jdbc41
我是运行以下查询:
SELECT * FROM foo;
'foo' 的架构如下:
CREATE TABLE foo
(
gid integer NOT NULL DEFAULT nextval('address_gid_seq'::regclass),
objectid numeric(10,0),
house_num integer,
half_add character varying(4),
pre_dir character varying(2),
st_name character varying(50),
st_type character varying(4),
suf_dir character varying(2),
unit_type character varying(4),
unit_id character varying(6),
city character varying(15),
state character varying(2),
zipcode numeric(10,0),
angle numeric,
parcel_num character varying(11),
idnum numeric(10,0),
status character varying(1),
status_dat date,
esnnum character varying(5),
geom geometry(Point,3857),
CONSTRAINT address_pkey PRIMARY KEY (gid)
)
我没有创建这个 table,所以我不确定可能出了什么问题,但行数(使用 pgAdmin3 作为快捷方式完成)约为 250,000,因此有明显的数据在那里。要求通过 'limit' 获取一些数据是可行的,尽管它非常慢。
我可以在调试器中暂停我的查询,它会在以下堆栈中暂停:
PSQLWarning(SQLException).setNextException(SQLException) line: 294
PSQLWarning(SQLWarning).setNextWarning(SQLWarning) line: 213
Jdbc4ResultSet(AbstractJdbc2ResultSet).addWarning(SQLWarning) line: 2669
AbstractJdbc2ResultSet$CursorResultHandler.handleWarning(SQLWarning) line: 1841
QueryExecutorImpl.handleWarning(SQLWarning) line: 2179
QueryExecutorImpl.processResults(ResultHandler, int) line: 2023
QueryExecutorImpl.fetch(ResultCursor, ResultHandler, int) line: 2201
Jdbc4ResultSet(AbstractJdbc2ResultSet).next() line: 1924
我真的没有太多时间来了解 Postgres 的 JDBC 驱动程序是如何实现的,所以我想我大声疾呼,看看是否有其他人经历过这种情况,是否有什么问题table 中的数据有误。如果我可以访问源数据,我也许可以在那一端修复它;但是针对现有 Postgres table 的查询会导致似乎是无限循环,这似乎很奇怪。
我应该补充一点,ResultSet.next() 永远不会进入调试器,代码只是无限期地停留在 setNextException() 方法中。
编辑: 我在 pgAdmin 的 "messages" 中得到了很多这样的东西:
NOTICE: [g_serialized.c:gserialized_get_type:50] entered
NOTICE: [lwgeom.c:lwgeom_set_srid:1455] entered with srid=3857
NOTICE: [lwgeom.c:lwgeom_is_empty:1233] lwgeom_is_empty: got type Point
NOTICE: [lwout_wkb.c:lwgeom_to_wkb:710] WKB output size: 25
NOTICE: [lwout_wkb.c:lwgeom_to_wkb:723] Hex WKB output size: 51
NOTICE: [lwgeom.c:lwgeom_is_empty:1233] lwgeom_is_empty: got type Point
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:393] Entering function, buf = 0x2acec3c3e770
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:395] Endian set, buf = 0x2acec3c3e772
NOTICE: [lwout_wkb.c:integer_to_wkb_buf:189] Writing value '536870913'
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:398] Type set, buf = 0x2acec3c3e77a
NOTICE: [lwout_wkb.c:integer_to_wkb_buf:189] Writing value '3857'
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:403] SRID set, buf = 0x2acec3c3e782
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:360] Writing point #0
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:364] Writing dimension #0 (buf = 0x2acec3c3e782)
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:364] Writing dimension #1 (buf = 0x2acec3c3e792)
NOTICE: [lwout_wkb.c:ptarray_to_wkb_buf:369] Done (buf = 0x2acec3c3e7a2)
NOTICE: [lwout_wkb.c:lwpoint_to_wkb_buf:407] Pointarray set, buf = 0x2acec3c3e7a2
NOTICE: [lwout_wkb.c:lwgeom_to_wkb:759] buf (0x2acec3c3e7a3) - wkb_out (0x2acec3c3e770) = 51
NOTICE: [g_serialized.c:gserialized_get_type:50] entered
NOTICE: [g_serialized.c:lwgeom_from_gserialized:1137] Got type 1 (Point), srid=3857
NOTICE: [g_serialized.c:lwgeom_from_gserialized_buffer:1091] Got type 1 (Point), hasz=0 hasm=0 geodetic=0 hasbox=0
client_min_messages
未显示任何设置。
这个问题的解决方法如评论所述:
将 client_min_messages
设置为 ERROR
。这将避免在每个几何记录 JDBC 上向客户端发送十几个错误消息,在我的例子中,这将至少提高一个数量级的性能。