标签: postgresql-12

为什么 OR 语句比 UNION 语句慢?

数据库版本:PostgreSQL 12.6

我有一张有 600,000 条记录的表。

该表具有以下列:

  • 名称 (varchar)
  • location_type (int) 枚举值:(1,2,3)
  • 血统(varchar)

索引:

  • 血统(btree)

祖先列是一种构建树的方法,其中每一行都有一个祖先,其中包含所有以“/”分隔的父 ID。

考虑以下示例:

ID 姓名 祖先
1 空值
5 节点 '1'
12 节点 '1/5'
22 叶子 '1/5/12'

以下查询需要 686 毫秒来执行:

SELECT * FROM geolocations
WHERE EXISTS (
   SELECT 1 FROM geolocations g2
   WHERE g2.ancestry =
      CONCAT(geolocations.ancestry, '/', geolocations.id)
)
Run Code Online (Sandbox Code Playgroud)

此查询在 808 毫秒内运行:

SELECT * FROM geolocations
WHERE location_type = 2
Run Code Online (Sandbox Code Playgroud)

将两个查询与 OR 结合使用时,如果它完成,则需要大约 4475 毫秒才能完成。

SELECT * FROM geolocations
WHERE EXISTS (
   SELECT 1 FROM …
Run Code Online (Sandbox Code Playgroud)

postgresql performance postgresql-12

11
推荐指数
3
解决办法
3097
查看次数

LIKE 不支持 PostgreSQL 不确定性排序规则

我正在使用 Postgresql v12。我创建了一个像这样的排序规则:

CREATE COLLATION ci (provider = icu, locale = 'tr_TR', deterministic = false);
Run Code Online (Sandbox Code Playgroud)

我在表中使用了该排序规则:

create table testtable1 (
    id serial  primary key,
    name text  COLLATE "ci"
);
Run Code Online (Sandbox Code Playgroud)

我插入了示例数据:

insert into testtable1 values(3,'abc');
Run Code Online (Sandbox Code Playgroud)

当我使用 查询该表时LIKE,它返回以下错误:

select name from testtable1 WHERE name LIKE '%a%'  
Run Code Online (Sandbox Code Playgroud)


错误:LIKE SQL 状态不支持非确定性排序规则:0A000

但我需要使用LIKE. 有什么办法允许这样做吗?

collation unicode case-sensitive international-components-unicode postgresql-12

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

Postgres COPY 与冲突忽略 - 可能吗?

我想在 Postgres 命令中添加冲突忽略copy。我知道我可以将数据复制到没有唯一索引/主键的表中,然后使用插入语法on conflict。但我想知道这是否可以直接来自COPY

postgresql copy postgresql-12

10
推荐指数
1
解决办法
7591
查看次数

不区分大小写的排序规则仍然比较区分大小写

目前我正在试图创建一个表,一个文本列将比较案例默认情况下是敏感的。这是因为我们有一个第三方程序可以对我们的数据库执行搜索。该SELECT程序使用的语句不能更改。

抽象的问题是我们不知何故需要这个搜索不区分大小写,但它目前是区分大小写的。

我读到 Postgres 12 确实支持允许这种行为的非确定性排序规则。

我在德国 Windows 机器上安装了 Postgres 服务器(版本 PostgreSQL 12.1,由 Visual C++ build 1914 编译,64 位)。

因此,出于测试目的,我创建了一个新数据库进行测试:

CREATE DATABASE collation_test
    WITH 
    OWNER = postgres
    ENCODING = 'UTF8'
    CONNECTION LIMIT = -1;
Run Code Online (Sandbox Code Playgroud)

在这个数据库中,我创建了以下排序规则,我在一篇关于这些排序规则的文章中找到

CREATE COLLATION collat_ci (
  provider = 'icu',
  locale = 'und-u-ks-level2',
  deterministic = false
);
Run Code Online (Sandbox Code Playgroud)

在此之后,我需要一个表来测试这个排序规则

CREATE TABLE public.person
(
    "Id" bigint NOT NULL,
    "Name" text COLLATE public.collat_ci,
    PRIMARY KEY ("Id")
);

ALTER TABLE public.person
    OWNER to postgres;

INSERT …
Run Code Online (Sandbox Code Playgroud)

postgresql collation case-sensitive postgresql-12

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

FATAL 53300:剩余连接槽保留用于非复制超级用户连接

我有一个在远程托管 VM 服务器 (Windows Server 2019) 上运行的 PostgreSQL 12.1 数据库系统(我将其称为 PGSQL)。几个月前我们升级了服务器操作系统和 PGSQL。从那时起,一切都或多或少地正常运行,直到今天早上,我开始在几乎每个连接到此 PGSQL 实例的内部应用程序中收到上述数据库错误。

为了检查连接,我运行了SELECT * FROM pg_stat_activity;,它返回了 103 行。我的postgresql.conf文件有max_connections = 100,所以这是有道理的,但没有意义的是,在这 103 个连接中,其中 90 多个连接被idle列为DISCARD ALL. 所有这些都显示为由同一非超级用户帐户从服务器自己的内部地址执行。但是,一些连接显示query_start一个月或更长时间前的日期值。

现在,不幸的是,我们现有的许多应用程序都是使用硬编码凭据构建的(我对继承的这些应用程序的代码有很多“清理”工作要做),并且通常是从指向的快捷方式执行的到托管 PGSQL 数据库的服务器上的“应用程序”共享,因此所有这些看起来都不是特别“可疑”。我试图简单地终止使用前一个查询中的值SELECT pg_cancel_backend(<pid>);之一的进程pid,但重新查询pg_stat_activity仍然在结果集中显示相同的记录(据我所知,所有值似乎完全相同)。

也许我没有使用正确的函数来终止这些“挂起”的进程或其他东西,但我无法弄清楚如何单独清除这些连接。因为我需要让我们的生产环境恢复到可用状态,所以我最终只是停止并重新启动服务器上的 PGSQL 服务,这确实清除了所有旧的DISCARD ALL语句,但我很好奇是否可以采取一些措施来防止这种积压的“挂”报表日后出现。

我的问题是,我怎样才能防止这种情况再次发生?需要注意的一件事是,在将 PGSQL 服务器升级到 v12.1 之前,我们运行了 v9.4 多年,并且从未遇到过此问题。我想知道是否有较新版本的 PGSQL 固有的问题,或者甚至可能是在 Windows Server 2019 环境中运行 PGSQL 的问题导致了此行为。


编辑

为了参考和整理,以下信息来自评论:

我没有任何服务器端用于管理连接池(我在有关PgBouncer的其他问题中看到了一些参考资料,但还没有机会查看它是否对我们的环境有帮助)。我的大多数应用程序都通过Npgsql …

postgresql max-connections postgresql-12

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

从 Postgres 11 升级到 Postgres 12 使某些查询速度慢了 300 倍,可能是由于新的 CTE 处理

我的应用程序当前使用 PostgreSQL 11.6。今天,我在虚拟机上测试了 PostgreSQL 12.1,结果令人震惊:一个重要查询在版本 11(同一虚拟机)上需要 100 毫秒,现在在 Postgres 12 上只需要大约 36 秒。这慢了 300 多倍。

我怀疑 CTE 的新处理方式,即MATERIALIZED,NOT MATERIALIZED是造成这种情况的原因。

如果我将每个 CTE 更改为MATERIALIZED,查询时间将从 36 秒减少到 6 秒。明显好一些,但仍然比版本 11 慢 50 倍以上。

如果我没猜错的话,在 PostgreSQL 12 中你有两个替代选项:

  • 使用MATERIALIZEDCTE 只执行一次,但你失去了索引的好处
  • 您可以获得NOT MATERIALIZED索引的好处,但每次访问其结果时都会执行您的 CTE。

那是对的吗?

是否有任何技巧,例如返回 Postgres 11 行为的特殊设置?或者是处理此问题的唯一方法,手动评估每个 CTE 是否MATERIALIZED更好NOT MATERIALIZED

我想,很多时候并不清楚哪种方式更好。我的应用程序包含数百个 CTE,其中许多都执行表查询和昂贵的函数调用(文档中的示例,他们说这NOT MATERIALIZED更好)。

编辑: 我检查过的内容以使结果具有可比性:

  • 同一虚拟机
  • 相同且非常小的数据集
  • 相同的 postgresql.conf
  • 重新索引
  • vacuum analyze

结果EXPLAIN ANALYZE …

cte upgrade postgresql-12 postgresql-performance

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

在 postgres 12 中使用 jit 处理性能问题

tl; dr:处理由 jit 引起的性能下降的最佳方法是什么?

背景

最近我从 postgres 11 迁移到 12 并注意到,一些查询/程序运行得相当慢。我做了一些研究并测试了不同的配置 - 结果表明 jit 开销超过了它的收益。我看到两种可能的解决方案:

  1. 通过运行set jit = off;一次永久禁用所有查询的 jit 。这有帮助,但感觉不自然。(也许是因为更改了默认配置,我没有做太多,因为没有这样的需要。默认值是理智的,需要更改的可能性很小。)这也意味着在运行长查询时放弃可能的性能提升.

  2. 在程序开始时禁用 jit 并在结束时启用它。我反对更改配置对并行运行的查询的影响。当然,这会损害日志查询的性能,这些查询会同时运行,但这可能会导致其他可能难以检测的错误。此外,这似乎比第一个解决方案更不正确 - 作为程序的一部分更改配置。

处理这个问题的最好方法是微调配置,这样 jit 就不会被完全丢弃,而且配置也不会在运行时改变。不幸的是,我发现几乎没有任何资源如何,这将是可能的(只有像参数jit_above_cost的文件,似乎是帮助不大)。

问题:解决此问题的最佳方法是什么?除了运行和测量之外,是否有关于何时禁用 jit 的任何标准?是否可以微调行为(例如,针对特定查询禁用 jit)?

编辑:我附上了一个没有jit的计划。计划太大了,不能在这里张贴。

postgresql postgresql-12 jit

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

为什么使用 GiST 索引来过滤非前导列?

我总是了解到并理解,只有当我们对前导(或所有)列有谓词时才能使用索引。现在,令我惊讶的是,我注意到以下查询中使用了GiST 索引。这是为什么?这是 GiST 索引的特殊功能吗?

CREATE TABLE t1 (
    i INT, 
    j INT, 
    k INT
);

INSERT INTO t1 
SELECT i, j, k 
FROM   GENERATE_SERIES(1, 100) AS i, 
       GENERATE_SERIES(1, 100) AS j, 
       GENERATE_SERIES(1, 100) AS k;

CREATE INDEX ON t1 USING GiST(i, j, k);

EXPLAIN SELECT * FROM t1 WHERE k = 54;
Run Code Online (Sandbox Code Playgroud)
QUERY PLAN
Bitmap Heap Scan on t1  (cost=199.03..5780.51 rows=5000 width=12)
  Recheck Cond: (k = 54)
  ->  Bitmap Index Scan on t1_i_j_k_idx  (cost=0.00..197.78 rows=5000 width=0)
        Index Cond: …
Run Code Online (Sandbox Code Playgroud)

postgresql index-tuning gist-index postgresql-12

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

为什么无法转换为 PostgreSQL 索引中的时间戳?

我正在处理从外部源收到的 JSON 文档。在本文档中,有一个timestamp属性对应于timestampPostgreSQL 数据类型的文本格式。换句话说,它可以被转换为timestamp类型:(data->>'timestamp')::timestamp

我想timestamp在索引中使用该属性。我尝试了以下方法:

create table t
(
    data    jsonb
);

create index on t(((data->>'timestamp')::timestamp));
Run Code Online (Sandbox Code Playgroud)

我正进入(状态:

ERROR:  functions in index expression must be marked IMMUTABLE
Run Code Online (Sandbox Code Playgroud)

为什么是这样?我知道转换为 atimestamptz并不是不可变的,因为本地化配置设置不是静态的,但我无法将该逻辑应用于转换为timestamp.

还有办法将我的timestamp财产放入索引吗?

我正在使用几天前发布的 PostgreSQL 12。

postgresql index timestamp cast postgresql-12

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

优化 Postgresql 中的选择计数结果

我正在尝试优化包含超过 8000 万行的表。需要 20 多分钟才能获得行计数结果。我尝试过集群、vacuum full 和重新索引,但性能没有提高。为了改进数据查询和检索,我需要配置或调整什么?我在 Windows 2019 下使用 Postgresql 12。

更新信息:

  • 目前总行数约为 9200 万以上
  • 表列数 = 44
  • Explain query result using 'select count(*) from doc_details':  
        Finalize Aggregate  (cost=5554120.84..5554120.85 rows=1 width=8) (actual time=1249204.001..1249210.027 rows=1 loops=1)  
      ->  Gather  (cost=5554120.63..5554120.83 rows=2 width=8) (actual time=1249203.642..1249210.020 rows=3 loops=1)  
            Workers Planned: 2  
            Workers Launched: 2  
            ->  Partial Aggregate  (cost=5553120.63..5553120.63 rows=1 width=8) (actual time=1249153.615..1249153.616 rows=1 loops=3)  
                  ->  Parallel Seq Scan on doc_details  (cost=0.00..5456055.30 rows=38826130 width=0) (actual time=3.793..1245165.604 rows=31018949 loops=3)  
    Planning Time: 1.290 ms  
    Execution Time: …
    Run Code Online (Sandbox Code Playgroud)

postgresql count postgresql-12 query-performance

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