标签: postgresql-performance

Postgres 的哪些查询比 MySQL InnoDB 更快

我已经阅读了相同架构/查询的 MySQL 和 PostgreSQL 之间的性能差异。以下是对文章的简要复述:

PostgreSQL 表是堆表(意味着没有聚集索引)......(Postgres)表的主键查找需要点击索引,查找文件中的位置,然后点击堆表并拉出记录。这意味着随机磁盘 I/O 的数量... InnoDB 使用不同的方法。使用 InnoDB,表是一个 b 树索引(聚集,物理排序)...... PK 查找所需的随机磁盘 I/O 更少......同时,索引扫描需要遍历两个索引而不是一个(index -> PK index -> table row ),这意味着使用主键以外的任何索引最终都会变慢,而顺序扫描仍然更慢。

哪种查询使用 Postgres 比使用 MySQL InnoDB 快得多?

我理解为什么 PK 查找对于 MySQL 来说要好得多。我不明白:

  1. 为什么通过两个索引(InnoDB,通过非 PK 索引查找)查找要慢得多?它是否需要两倍以上的 I/O 或 CPU?它可以弥补 PK 查找提升的巨大好处吗?
  2. 为什么 InnoDB 顺序扫描更慢?

PS Internet 说 Postgres 更适合复杂查询和子查询,但我仍然不明白为什么它更好?

mysql rdbms postgresql performance query-performance postgresql-performance

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

永远不会完成的查询的日志计划

我们在每晚凌晨 2 点的负载中有一个更新,它有两次将 CPU 固定在 100% 并且在几个小时后从未完成。我强烈怀疑这是因为统计数据不准确导致连接中出现嵌套循环。我无法在具有相同硬件规格和 postgres 配置的较低环境中重现它。

我需要证明嵌套循环正在发生,然后才能放入 RFC 来解决问题(例如调整分析和自动真空设置)。我已经设置了 auto_explain 但这似乎只捕获了实际完成的查询的计划。如何为未完成的查询记录计划?

在 SQL Server 中,我可以通过使用 @get_plans=1 运行 sp_whoisactive 来做到这一点。我正在 Postgres 中寻找类似的东西。到目前为止,我唯一的想法是使用 cron 运行 EXPLAINs,但这似乎非常复杂。

postgresql performance postgresql-performance

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

多个相关表的全文搜索:索引和性能

我们有以下数据库结构

CREATE TABLE objects (
    id       int   PRIMARY KEY,
    name     text,
    address  text
);

CREATE TABLE tasks (
    id int           PRIMARY KEY,
    object_id int    NOT NULL,
    actor_id int     NOT NULL,
    description text
);

CREATE TABLE actors (
    id   int  PRIMARY KEY,
    name text
);
Run Code Online (Sandbox Code Playgroud)

用户输入以空格分隔的单词列表(基本上是搜索词),我们必须搜索满足以下条件的任务:如果每个搜索词在任务描述的串联中至少出现一次,则该任务是“匹配”,其关联对象的名称和地址以及关联参与者的名称。

现在,如果我们不关心性能,我们可以这样做(给定查询“foo bar”):

SELECT t.id, t.description
FROM tasks AS t
INNER JOIN actors AS a ON t.actor_id = a.id
INNER JOIN objects AS o ON t.object_id = o.id
WHERE to_tsvector(concat_ws(' ', t.description, o.name, o.address, a.name)) @@ …
Run Code Online (Sandbox Code Playgroud)

postgresql performance full-text-search postgresql-performance

6
推荐指数
2
解决办法
6365
查看次数

Postgres 9.0 与 Postgres 10 和 11 的性能对比

我们想将我们的数据库从虚拟主机提供商 (postgres 9.0) 移动到我们的本地网络服务器(尝试了 postgres 10 和最新的 11)我们的机器是 windows 服务器,具有 16gb ram 的快速 XEON 机器,仅用于数据库。

但即使在提高 default_statistics_targer = 4000 并分析统计数据之后,我们也无法运行许多以前运行非常快的视图。似乎虚拟主机提供商的服务器经过了微调,我们的执行计划可能出于某种原因很奇怪。

我们的 Postgres 是库存安装配置。

简化的示例查询如下(最大的表是“dale 表,它有几百万条记录大(它是带有外键的绑定表)其他表要小得多,一万条记录(系统是真空分析的,它是全新安装的)

EXPLAIN ANALYZE
SELECT REKLAMACNY_LIST.ID REKLAMACNY_LIST_ID
FROM REKLAMACNY_LIST
WHERE REKLAMACNY_LIST.VALIDTO IS NULL
  AND
    ( SELECT NOT tr.typ_odstupenia::boolean
     AND sr.konecny_stav::boolean
     FROM dale d1
     CROSS JOIN typ_reklamacie tr
     CROSS JOIN dale d2
     CROSS JOIN stav_reklamacie sr
     WHERE TRUE
       AND d1.fk7 = reklamacny_list.id
       AND d2.fk7 = reklamacny_list.id
       AND d1.fk1 = tr.id
       AND d2.fk3 = sr.id
       AND sr.validto IS NULL …
Run Code Online (Sandbox Code Playgroud)

postgresql performance postgresql-performance

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

Postgres 的 UPDATE SET x = NULL 策略

目前尚不清楚当列设置为 时 Postgres 采取的策略NULL

UPDATE tbl SET
  col1 = NULL,
  col2 = NULL
WHERE created < current_date - INTERVAL '1 year';
Run Code Online (Sandbox Code Playgroud)

文档https://www.postgresql.org/docs/current/mvcc.html有点冗长和技术性,所以我无法可靠地推断:

是否就地执行设置为 NULL 或复制受影响的行/页

看起来任何 UPDATE 都应该为 MVCC 语义创建新行,但如果设置为 NULL 是一种特殊情况怎么办?

为了遵守 GDPR,我认为要清空所有个人历史数据,并尝试理解大规模定期数据的含义UPDATE SET x = NULL。我应该考虑VACUUM之后吗?

postgresql vacuum postgresql-performance

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

如何通过子查询或连接来利用分区修剪?

我有一个分区表...

CREATE TABLE erco.rtprices
(
    scedtime timestamp with time zone NOT NULL,
    node_id integer NOT NULL,
    lmp numeric(12,6),
    CONSTRAINT rtprices_pkey PRIMARY KEY (scedtime, node_id)
) PARTITION BY LIST (node_id);
Run Code Online (Sandbox Code Playgroud)

每个都有node_id自己的分区。

如果我进行直接查询(第一个版本),例如:

explain select scedtime, lmp 
from erco.rtprices
where node_id = 11111
Run Code Online (Sandbox Code Playgroud)

然后该计划仅对rtprices_11111分区进行顺序扫描。 这就是我要的。

但是,如果我执行(第二个版本)查询,例如

explain select scedtime, lmp 
from erco.rtprices
inner join erco.nodes using (node_id)
where nodename = 'somename'
Run Code Online (Sandbox Code Playgroud)

那么该计划包括对每个分区进行顺序扫描,即使此查询与第一个查询一样有限制。

我尝试了上述查询的另一种形式(第三个版本)。

explain select scedtime, lmp 
from erco.rtprices
where node_id = (select node_id from erco.nodes where nodename='somename') …
Run Code Online (Sandbox Code Playgroud)

postgresql execution-plan partitioning postgresql-performance postgresql-13

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

COUNT(1) OVER (PARTITION BY NULL) 的性能损失

在我的应用程序服务器中,我想使用LIMIT和对数据集进行分页OFFSET,并另外将数据集的总数返回给用户。

而不是对数据库进行两次远程调用:

select count(1) as total_count from foo;
select c1 from foo;
Run Code Online (Sandbox Code Playgroud)

我认为在单个数据库调用中完成此操作会更明智:

select c1, count(1) over (partition by null) from foo;
Run Code Online (Sandbox Code Playgroud)

但是,与不使用窗口函数相比,添加此窗口函数会导致执行时间长一个数量级。

我觉得这很令人惊讶,因为类似的时间select count(1) from foo只需要两倍的时间select c1 from foo。然而,将其转换为窗口函数会导致性能下降。

此外,使用以下使用子查询的替代方案非常快:

select c1, (select count(1) from foo) as total_count from foo;
Run Code Online (Sandbox Code Playgroud)

我本来期望 postgresql 能够优化partition by null

我在 Oracle 中尝试过这一点,发现了类似的性能损失。

如何解释为什么这里会出现性能损失?对于核心 postgresql 开发人员来说,进行更改以优化这一点是否相对容易,甚至值得,例如通过将 PARTITION BY NULL 的窗口函数转换为子查询?


设置:

drop table foo;
create table foo (c1 int);

insert into foo
select i from …
Run Code Online (Sandbox Code Playgroud)

postgresql count window-functions postgresql-performance postgresql-13

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

如何通过许多重复的 UNION 子查询来减少查询大小?

我使用 Postgres 13 并使用以下 DDL 定义了一个表:

CREATE TABLE item_codes (
    code    bytea                    NOT NULL,
    item_id bytea                    NOT NULL,
    time    TIMESTAMP WITH TIME ZONE NOT NULL,
    PRIMARY KEY (item_id, code)
);

CREATE INDEX ON item_codes (code, time, item_id);
Run Code Online (Sandbox Code Playgroud)

我使用以下查询:

SELECT DISTINCT time, item_id
FROM (
      (SELECT time, item_id
       FROM item_codes
       WHERE code = '\x3965623166306238383033393437613338373162313934383034366139653239'
       ORDER BY time, item_id
       LIMIT 100)
       UNION ALL
      (SELECT time, item_id
       FROM item_codes
       WHERE code = '\x3836653432356638366638636338393364373935343938303233343363373561'
       ORDER BY time, item_id
       LIMIT 100)
     ) AS items
ORDER …
Run Code Online (Sandbox Code Playgroud)

postgresql execution-plan union query-performance postgresql-performance

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

为什么 PostgreSQL 数据库表上的“DELETE”操作异常缓慢?

在 PostgreSQL 数据库表上执行“DELETE”操作时,我遇到了严重的性能问题。删除 15488 条记录的执行时间为 79423.768 毫秒,与“INSERT”或“SELECT”等其他操作相比非常慢。对于为什么会发生这种情况以及优化删除操作的可能方法,我将不胜感激。

背景:我使用 PostgreSQL 引擎版本 12.14 作为应用程序的后端,并且我注意到从一个表中删除记录需要花费出乎意料的长时间。涉及的表定义了索引和约束,数据库大小相对较小,预计会增长到几 GB。然而,对于这个特定的表,这个问题似乎更加明显,而其他表则表现良好。

硬件是 AWS db.t2.micro 实例,具有 1 个 CPU 核心、1 (GiB) 内存和 20 (GiB) 通用 SSD 用于存储。

column_name_loading表架构,我们尝试从中删除的表。

列名称 数据类型 描述
ID 文本 首要的关键
散列 文本 首要的关键
日期_从 时间戳 首要的关键
日期到 时间戳
测量位置uuid 通用唯一标识符 主键、外键
列名 文本 不为空
统计类型id 文本
被忽略 布尔值
笔记 文本
更新时间 时间戳
更新者 通用唯一标识符

可以看到,上表有一个复合主键,涉及4列。有两个表具有对该column_name_loading表的外键引用

第一桌

ALTER  TABLE
logger_main_config_column_name_loading 
ADD
CONSTRAINT column_name_loading_fkey FOREIGN KEY (
column_name_loading_measurement_location_uuid,
column_name_loading_id,
column_name_loading_hash,
column_name_loading_date_from
) REFERENCES …
Run Code Online (Sandbox Code Playgroud)

postgresql delete postgresql-performance slow-query

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

Postgres 中违反唯一键约束是否会导致性能损失?

在我的 API 中,当存在具有该唯一键的行时,用户可能会发送一个尝试创建新行的请求。

目前,我正在捕获唯一键错误并返回一条消息,指出 X 已存在。但是,首先查找该行(在同一连接上)并且仅在该行不存在时才运行 INSERT 语句是否会更高效?

我的直觉告诉我,从 PostgreSQL 读取错误应该会更有效,但我想确保我正在按照惯用的方式做事。

PostgreSQL 版本为 12

我的 API 中的唯一键不是代理 ID 值,它是由外键与文本值组合而成的组合。如果唯一键约束没有失败,数据库确实已经为此行生成了自己的代理 ID 。所以该行的 ID 不是我要检查的内容。正确的行为是不插入行,因为 FK/文本值在表中需要是唯一的。如果请求包含表中已存在的 FK/文本值,则不应插入任何行。

postgresql postgresql-performance

6
推荐指数
3
解决办法
1712
查看次数