实际查询更多,但我面临的问题可以归结为:
用于过滤单调递增整数行集的查询,以便 -在最终结果集中, row(n+1).value >= row(n).value + 5。
对于我需要解决的实际问题,行集计数在 1000 秒内。
举几个例子来澄清:
我设法通过以下查询获得了所需的结果,但它似乎过于复杂。取消注释不同的“..with t(k)..”以尝试它们。
我正在寻找任何简化或替代方法来获得相同的结果。
with recursive r(n, pri) as (
with t(k) as (values (1),(2),(3),(4),(5)) -- the data we want to filter
-- with t(k) as (values (1),(5),(7),(10),(11),(12),(13))
-- with t(k) as (values (6),(8),(11),(16),(20),(23))
-- with t(k) as (values (6),(8),(12),(16),(20),(23))
select min(k), 1::bigint from t -- bootstrap for recursive processing. 1 here represents rank().
UNION
select k, (rank() over(order …Run Code Online (Sandbox Code Playgroud) (编辑:请参阅结尾以获得更简单的示例)
我在一个名为“cases”(135k 行,29 列)的表中搜索。此表中的某些行具有父子关系类型(不同类型),这意味着对于这些记录,必须混合使用父/子字段来过滤和显示。
我已经确定了四种不同的父子关系并为它们创建了视图:
这些视图的结果不重叠,共同覆盖了表格的 100%。
当我选择所有这些的联合并分别过滤每个视图时,查询需要大约 9 毫秒。选择所有视图的联合并过滤其结果大约需要 500 毫秒。
我还在没有视图的情况下对此进行了测试,内联了它们包含的查询,但没有产生可衡量的改进。
这是快速查询(解释):
SELECT c.*
FROM caselist_no_specials c
JOIN case_clients cacl ON cacl.case_id = c.main_id
WHERE cacl.client_id = 12046
UNION ALL
SELECT c.*
FROM caselist_disputes_with_ipr c
JOIN case_clients cacl ON cacl.case_id = c.main_id
WHERE cacl.client_id = 12046
UNION ALL
SELECT c.*
FROM caselist_mark_children c
JOIN case_clients cacl ON cacl.case_id = c.main_id
WHERE cacl.client_id …Run Code Online (Sandbox Code Playgroud) 我发现很难理解为什么在这个查询中进行了一堆堆提取。据我了解,当索引中没有空值(两端)时,反向搜索索引应该与直接搜索一样快,反之亦然。
我怀疑向前/向后扫描实际上是一个红鲱鱼,但我无法识别此解释输出中的任何其他有意义的差异。
这是表格布局。我已将我认为与问题无关的前两列匿名化,但为了完整起见,我保留了它们及其索引。
testqueuedb=> \d+ queue
Table "public.queue"
Column | Type | Modifiers | Storage | Stats target | Description
-----------------------+--------------------------+-------------------------------------------------------------+----------+--------------+-------------
foo | character varying(64) | not null | extended | |
bar | numeric(6,0) | not null | main | |
worker | character varying(32) | not null | extended | |
queued | timestamp with time zone | not null default (timeofday())::timestamp without time zone | plain | |
Indexes:
"queue_idx_job" btree (foo, bar, worker)
"queue_idx_worker" btree (worker, …Run Code Online (Sandbox Code Playgroud) 使用普通的更新语句来更新 json(b) 列是否有任何缺点,如下所示:
update "events" set "properties" = '{"type":"graph"}'
Run Code Online (Sandbox Code Playgroud)
而不是使用 PostgreSQL 提供的 jsonb_set 函数,它会变成这样的语句:
update "events" set jsonb_set("properties", {'type'}, 'graph')
Run Code Online (Sandbox Code Playgroud)
当使用例如。一个 ORM,并在刚刚更新了 JSON 字段的模型上调用 .save(),第一个方法将被调用,但是由于 PostgreSQL 文档中没有提到这种做事方式,我担心这个可能有一些缺点。
鉴于我对数据库性能方面的任何事情都不太熟悉,我想我会来这里问一个问题。
提前致谢!
(这篇文章的后续内容:当我在子查询中 ORDER BY 时,为什么我的 PostgreSQL 表达式索引没有被使用?)
PostgreSQL 9.5。
我不能透露全部细节,但table有 22 列和 5 个索引:
text(btree)text(btree)timestamp with time zone(btree)tsvector(杜松子酒)bigint(btree)(从上一篇文章你知道我试图避免创建这个额外的列,只是使用表达式索引——将两integer列加在一起——没有成功。bigint这里的列可能只是“整数”,但我做了一个创建它时出错;添加列、填充它并重新编制索引花了大约一个小时,所以我希望这不相关,但要提及它以防万一。)
除了tsvector.
以下查询都只需要 12ms 并且只使用一个Index Scan:
SELECT pk FROM table ORDER BY pk DESC LIMIT 10SELECT pk FROM table ORDER BY text_column DESC LIMIT 10SELECT pk FROM table ORDER BY timestamp_column DESC LIMIT 10 …postgresql performance index optimization postgresql-9.5 postgresql-performance
我有一个分区表...
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
在我的应用程序服务器中,我想使用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
我使用 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
在 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) 在我的 API 中,当存在具有该唯一键的行时,用户可能会发送一个尝试创建新行的请求。
目前,我正在捕获唯一键错误并返回一条消息,指出 X 已存在。但是,首先查找该行(在同一连接上)并且仅在该行不存在时才运行 INSERT 语句是否会更高效?
我的直觉告诉我,从 PostgreSQL 读取错误应该会更有效,但我想确保我正在按照惯用的方式做事。
PostgreSQL 版本为 12
我的 API 中的唯一键不是代理 ID 值,它是由外键与文本值组合而成的组合。如果唯一键约束没有失败,数据库确实已经为此行生成了自己的代理 ID 。所以该行的 ID 不是我要检查的内容。正确的行为是不插入行,因为 FK/文本值在表中需要是唯一的。如果请求包含表中已存在的 FK/文本值,则不应插入任何行。
postgresql ×10
performance ×5
union ×2
count ×1
cte ×1
delete ×1
index ×1
json ×1
optimization ×1
partitioning ×1
recursive ×1
slow-query ×1
view ×1