在 PostgreSQL (8.4) 中,我试图将字符串参数转换为 SQL 查询中的日期,然后返回到now()
字符串不是有效日期(或为空)时。
在“伪SQL”中,这将是这样的:
SELECT CASE WHEN ? is not a valid date THEN now()::DATE ELSE CAST(? AS DATE) END;
Run Code Online (Sandbox Code Playgroud)
我尝试使用这两个查询来简化问题以检测空字符串:
SELECT CASE WHEN ?='' THEN now()::DATE ELSE CAST(? AS DATE) END;
SELECT DATE(CASE WHEN ?='' THEN now() ELSE ? END);
Run Code Online (Sandbox Code Playgroud)
例如,如果参数是''
,则相当于:
SELECT CASE WHEN ''='' THEN now()::DATE ELSE CAST('' AS DATE) END;
SELECT DATE(CASE WHEN ''='' THEN now() ELSE '' END);
Run Code Online (Sandbox Code Playgroud)
两者都失败了ERROR: invalid input syntax for type timestamp with time zone: …
我正在使用 PostgreSQL 8.4.15。在运行pg_dump
备份数据库时,出现以下错误:
pg_dump: SQL command failed
pg_dump: Error message from server: ERROR: missing chunk number 0 for toast value 123456789 in pg_toast_987654321
pg_dump: The command was: COPY public.my_table (id, .... all the columns ...)
Run Code Online (Sandbox Code Playgroud)
在搜索此错误消息时,我发现了一些建议重新索引表的参考文献(此处和此处)。(在这些讨论中,有提到查询pg_class
表以找到正确的pg_toast_XXXXXX
值,但似乎是因为它没有显示在他们的错误消息中。我跳过了这部分,因为我在错误消息中显示了一个值。我想这可能是由于 PostgreSQL 的更高版本而带来的便利。)
我运行了以下内容:
REINDEX table pg_toast.pg_toast_987654321;
VACUUM ANALYZE my_table;
Run Code Online (Sandbox Code Playgroud)
我现在可以毫无错误地使用了pg_dump
。
pg_toast
这些命令实际上做了什么以及做了什么?这些仅仅是简单的清理还是他们可以删除该表中的某些行?首先可能是什么导致了这个问题?
该表中大约有 300000 行,但我预计自上次成功备份以来只有大约 250 行新行(该表仅用于 INSERT/SELECT,没有 UPDATE)。
使用PostgreSQL(8.4),我创建总结了几桌各种结果的视图(例如创建列a
,b
,c
在视图中),然后我需要一些结果结合在同一个查询(例如a+b
,a-b
,(a+b)/c
, ...),从而产生最终结果。我注意到的是,每次使用中间结果时都会完全计算它们,即使它是在同一个查询中完成的。
有没有办法优化这个以避免每次都计算相同的结果?
这是一个重现问题的简化示例。
CREATE TABLE test1 (
id SERIAL PRIMARY KEY,
log_timestamp TIMESTAMP NOT NULL
);
CREATE TABLE test2 (
test1_id INTEGER NOT NULL REFERENCES test1(id),
category VARCHAR(10) NOT NULL,
col1 INTEGER,
col2 INTEGER
);
CREATE INDEX test_category_idx ON test2(category);
-- Added after edit to this question
CREATE INDEX test_id_idx ON test2(test1_id);
-- Populating with test data.
INSERT INTO test1(log_timestamp)
SELECT * FROM generate_series('2011-01-01'::timestamp, '2012-01-01'::timestamp, '1 hour'); …
Run Code Online (Sandbox Code Playgroud) 我试图在 PostgreSQL (8.4) 中表示树结构,以便能够查询从根到给定节点的路径或查找子分支中的所有节点。
下面是一个测试表:
CREATE TABLE tree_data_1 (
forest_id TEXT NOT NULL,
node_id TEXT NOT NULL,
parent_id TEXT,
node_type TEXT,
description TEXT,
PRIMARY KEY (forest_id, node_id),
FOREIGN KEY (forest_id, parent_id) REFERENCES tree_data_1 (forest_id, node_id)
);
CREATE INDEX tree_data_1_forestid_parent_idx ON tree_data_1(forest_id, parent_id);
CREATE INDEX tree_data_1_forestid_idx ON tree_data_1(forest_id);
CREATE INDEX tree_data_1_nodeid_idx ON tree_data_1(node_id);
CREATE INDEX tree_data_1_parent_idx ON tree_data_1(parent_id);
Run Code Online (Sandbox Code Playgroud)
每个节点由(forest_id, node_id)
(在另一个林中可以有另一个具有相同名称的节点)标识。每棵树都从一个根节点(其中parent_id
为空)开始,尽管我只希望每个森林都有一个。
这是使用递归 CTE 的视图:
CREATE OR REPLACE VIEW tree_view_1 AS
WITH RECURSIVE rec_sub_tree(forest_id, node_id, parent_id, depth, path, cycle) …
Run Code Online (Sandbox Code Playgroud) 我正在使用 PostgreSQL (8.4) 来存储由频繁插入的应用程序生成的数据(在下面描述的表结构中)。
数据库随着时间不断增长,并且由于新数据比旧数据更相关(在这个特定的应用程序中),删除旧行是一个合理的解决方案(基于 lowerid
或 old input_datetime
,或多或少相同) .
为了防止与此数据库(此服务器上运行的唯一数据库)相关的问题影响系统的其余部分,我将 PostgreSQL 数据目录放在其自己的分区(在 Linux 系统上为 ext3)。然而,当这个分区变满时,这会导致许多问题。
我正在考虑定期删除旧数据(例如DELETE FROM data_group WHERE id <= ...
通过 cron 作业)来解决这个问题。
首先,我的理解VACUUM
(由 auto-vacuum 执行,已开启)是,虽然它不一定将磁盘空间返还给操作系统(就像VACUUM FULL
那样),但它仍然允许将一些新数据插入到已使用的磁盘空间(即DELETE
s 不一定影响文件大小,但它们仍然在 PostgreSQL 自己的数据结构中释放空间)。这样对吗?(我注意到VACUUM FULL
应用程序本身引起了一些问题,可能是因为它使用了锁。)
如果是这样,它似乎也SELECT pg_database_size('my_database')
反映了磁盘上使用的大小,这不一定反映可用于进一步插入的内容。是否有另一种方法可以估算新插入物的可用空间?
此外,当为时已晚并且分区已填充到 100% 时,运行此DELETE
语句会导致此错误并导致 PostgreSQL 服务崩溃:
恐慌:无法写入文件“pg_xlog/xlogtemp.7810”:设备上没有剩余空间
PostgreSQL 守护进程停止当然是一个主要问题(并且在这台机器上没有其他磁盘可以将集群移动到)。
是否有防止此类问题发生的通用策略(知道磁盘空间受限于给定分区内,但删除旧数据是可以接受的)?我想在没有root
or postgres
(或 PostgreSQL 管理员)干预的情况下尽可能多地自动化。
CREATE TABLE data_group (
id SERIAL PRIMARY KEY,
name TEXT,
input_datetime TIMESTAMPTZ
);
CREATE …
Run Code Online (Sandbox Code Playgroud) 应用程序正在写入遵循 EAV 结构的数据库,类似于:
CREATE TABLE item (
id INTEGER PRIMARY KEY,
description TEXT
);
CREATE TABLE item_attr (
item INTEGER REFERENCES item(id),
name TEXT,
value INTEGER,
PRIMARY KEY (item, name)
);
INSERT INTO item VALUES (1, 'Item 1');
INSERT INTO item_attr VALUES (1, 'height', 20);
INSERT INTO item_attr VALUES (1, 'width', 30);
INSERT INTO item_attr VALUES (1, 'weight', 40);
INSERT INTO item VALUES (2, 'Item 2');
INSERT INTO item_attr VALUES (2, 'height', 10);
INSERT INTO item_attr VALUES (2, 'weight', 35); …
Run Code Online (Sandbox Code Playgroud) 我有一个可以包含相当大的BYTEA
值的表(同样适用于大TEXT
值)。它看起来像这样:
CREATE TABLE testtable (
id SERIAL PRIMARY KEY,
name TEXT UNIQUE NOT NULL, -- This is just an example: this could be the PK
value BYTEA -- This could be TEXT
);
Run Code Online (Sandbox Code Playgroud)
如果使用此表的应用程序尝试使用相同的 插入两行name
,我会在日志中收到此错误(当然,这是预期错误):
CREATE TABLE testtable (
id SERIAL PRIMARY KEY,
name TEXT UNIQUE NOT NULL, -- This is just an example: this could be the PK
value BYTEA -- This could be TEXT
);
Run Code Online (Sandbox Code Playgroud)
虽然记录错误以及记录语句(在此特定上下文中可能还有“name”的值)很有用,但记录 longBYTEA
或TEXT
value 不是。事实上,日志中的二进制数据以文本形式(例如 …
postgresql ×7
performance ×3
bytea ×1
cte ×1
disk-space ×1
eav ×1
join ×1
log ×1
optimization ×1
tree ×1
vacuum ×1
view ×1