小编Bru*_*uno的帖子

具有默认回退值的类型转换

在 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 type-conversion

13
推荐指数
1
解决办法
1万
查看次数

pg_dump 和错误:toast 值缺少块号 0

我正在使用 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

11
推荐指数
1
解决办法
2万
查看次数

PostgreSQL:在同一查询中重用复杂的中间结果

使用PostgreSQL(8.4),我创建总结了几桌各种结果的视图(例如创建列abc在视图中),然后我需要一些结果结合在同一个查询(例如a+ba-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 performance

8
推荐指数
1
解决办法
3646
查看次数

PostgreSQL 树结构和递归 CTE 优化

我试图在 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 performance tree optimization cte

6
推荐指数
1
解决办法
5641
查看次数

PostgreSQL 处理磁盘填满的策略

我正在使用 PostgreSQL (8.4) 来存储由频繁插入的应用程序生成的数据(在下面描述的表结构中)。

数据库随着时间不断增长,并且由于新数据比旧数据更相关(在这个特定的应用程序中),删除旧行是一个合理的解决方案(基于 lowerid或 old input_datetime,或多或少相同) .

为了防止与此数据库(此服务器上运行的唯一数据库)相关的问题影响系统的其余部分,我将 PostgreSQL 数据目录放在其自己的分区(在 Linux 系统上为 ext3)。然而,当这个分区变满时,这会导致许多问题。

我正在考虑定期删除旧数据(例如DELETE FROM data_group WHERE id <= ...通过 cron 作业)来解决这个问题。

首先,我的理解VACUUM(由 auto-vacuum 执行,已开启)是,虽然它不一定将磁盘空间返还给操作系统(就像VACUUM FULL那样),但它仍然允许将一些新数据插入到已使用的磁盘空间(即DELETEs 不一定影响文件大小,但它们仍然在 PostgreSQL 自己的数据结构中释放空间)。这样对吗?(我注意到VACUUM FULL应用程序本身引起了一些问题,可能是因为它使用了锁。)

如果是这样,它似乎也SELECT pg_database_size('my_database')反映了磁盘上使用的大小,这不一定反映可用于进一步插入的内容。是否有另一种方法可以估算新插入物的可用空间?

此外,当为时已晚并且分区已填充到 100% 时,运行此DELETE语句会导致此错误并导致 PostgreSQL 服务崩溃:

恐慌:无法写入文件“pg_xlog/xlogtemp.7810”:设备上没有剩余空间

PostgreSQL 守护进程停止当然是一个主要问题(并且在这台机器上没有其他磁盘可以将集群移动到)。

是否有防止此类问题发生的通用策略(知道磁盘空间受限于给定分区内,但删除旧数据是可以接受的)?我想在没有rootor postgres(或 PostgreSQL 管理员)干预的情况下尽可能多地自动化。


CREATE TABLE data_group (
    id SERIAL PRIMARY KEY,
    name TEXT,
    input_datetime TIMESTAMPTZ
);

CREATE …
Run Code Online (Sandbox Code Playgroud)

postgresql disk-space vacuum

6
推荐指数
1
解决办法
3792
查看次数

使用 EAV 结构视图优化查询

应用程序正在写入遵循 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)

postgresql performance join view eav

5
推荐指数
1
解决办法
3546
查看次数

限制 PostgreSQL 日志记录

我有一个可以包含相当大的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”的值)很有用,但记录 longBYTEATEXTvalue 不是。事实上,日志中的二进制数据以文本形式(例如 …

postgresql log bytea

5
推荐指数
1
解决办法
603
查看次数