标签: postgresql-performance

Postgres 中的 EXISTS() 与 EXISTS() = TRUE

面临奇怪的行为EXISTS(也适用于NOT EXISTS)生成不同的执行计划

WHERE EXISTS(...)

EXPLAIN ANALYZE
SELECT * FROM books
WHERE EXISTS (SELECT 1 FROM authors WHERE id = books.author_id AND name LIKE 'asd%');

| QUERY PLAN                                                                                                     |
| -------------------------------------------------------------------------------------------------------------- |
| Hash Join  (cost=218.01..454.43 rows=56 width=40) (actual time=0.975..0.975 rows=0 loops=1)                    |
|   Hash Cond: (books.author_id = authors.id)                                                                    |
|   ->  Seq Scan on books  (cost=0.00..206.80 rows=11280 width=40) (actual time=0.010..0.010 rows=1 loops=1)     |
|   ->  Hash  (cost=217.35..217.35 rows=53 width=4) (actual time=0.943..0.943 rows=0 loops=1)                    |
|         Buckets: …
Run Code Online (Sandbox Code Playgroud)

postgresql exists postgresql-performance

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

这是 DELETE ... WHERE EXISTS 查询计划 O(n*2) 还是 O(n^2) ?

我正在尝试执行一项常见任务,从表中删除重复项,目的是添加唯一约束。

CREATE TABLE IF NOT EXISTS item_identifier (
    pk       BIGSERIAL PRIMARY KEY,
    prefix   INTEGER NOT NULL,
    suffix   VARCHAR(1024) NOT NULL
);
CREATE INDEX temp_prefix_suffix_idx ON item_identifier (prefix, suffix);
Run Code Online (Sandbox Code Playgroud)

我想使用常见查询删除重复项,该查询可以在本网站的许多答案中找到。我认为重复率大约为 1%,因此没有太多需要删除的内容。

提供索引纯粹是为了帮助重复数据删除,稍后将被删除。不过,如您所见,PostgreSQL 甚至没有使用它!

有 2,759,559,168 行。索引temp_prefix_suffix_idx本身约为 100 GB。花CREATE INDEX了 12 个小时所以我不指望DELETE会很快。但根据 10% 的样本集,我推断需要 20 小时,而实际上已经花了 40 小时。对于我的示例方法来说,它可能仍在误差范围内,但我担心由于它不使用索引,这将花费指数时间。

EXPLAINSeq Scan on item_identifier aSeq Scan on item_identifier b

EXPLAIN DELETE FROM item_identifier a
  WHERE EXISTS
    (SELECT FROM item_identifier b
       WHERE a.prefix …
Run Code Online (Sandbox Code Playgroud)

postgresql exists query-performance postgresql-performance

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

使用 := 运算符赋值

当我分配一个变量时

result := title || '', by '' || author;
Run Code Online (Sandbox Code Playgroud)

运行该函数需要更多时间(大约 15 秒)。
但是,当我分配变量时

result = title || '', by '' || author;
Run Code Online (Sandbox Code Playgroud)

只需要133ms。

为什么第一个场景需要更多时间?这背后的原因是什么?

下面给出了完整的功能。

CREATE OR REPLACE FUNCTION myschema.fn_get_res_no(reservation_no character varying)
  RETURNS character varying AS
$BODY$  

DECLARE  
    emd_status_firstcall varchar(2);  
    emd_status_secondcall varchar(2);
    emd_status      varchar(6);  
BEGIN  
    SELECT firstwscomplete, secondwscomplete
    INTO emd_status_firstcall, emd_status_secondcall
    FROM myschema.mytable
    WHERE respkgconfirmid = reservation_no;

    emd_status = emd_status_firstcall || ', ' || emd_status_secondcall;
    RETURN emd_status ;  

END;  
$BODY$
  LANGUAGE plpgsql VOLATILE;
Run Code Online (Sandbox Code Playgroud)

postgresql performance plpgsql postgresql-performance

4
推荐指数
1
解决办法
8152
查看次数

位串上的 PostgreSQL 索引

在位串列上创建索引的最佳方法是什么?假设我有一个 type 列,bit(4)我想搜索所有设置了特定位的条目。所以如果我有条目:

bitfield | ...
--------------
1001
1010
0110
0010
0000 
Run Code Online (Sandbox Code Playgroud)

如果我试图搜索所有0010设置的条目,我可以轻松地做到这一点。但是我可以使用索引来优化搜索吗?

postgresql performance index postgresql-performance

4
推荐指数
1
解决办法
1983
查看次数

PostgreSQL - 日期时间范围重叠

我有一个包含日期时间字段startend. 我有一个(开始,结束)项目列表。我需要检查列表中的哪些项目与表中的数据重叠。当前查询如下所示:

select br.duration from booking, (
    select tstzrange('2016-09-06 03:45:00+00', '2016-09-06 14:45:00+00') as duration 
    union select tstzrange('2016-09-06 14:45:00+00', '2016-09-06 15:45:00+00') as duration
    -- other items from my list
) as br 
where tstzrange(start, end) && br.duration
Run Code Online (Sandbox Code Playgroud)

有没有其他方法可以做到?如果我在表中有数百万行并将它们与列表中的数百个项目进行比较,您认为它会起作用吗?

postgresql performance gist-index range-types postgresql-performance

4
推荐指数
1
解决办法
2635
查看次数

加速数百万行的计数查询

假设一个充满产品的数据库。一个产品可以恰好属于 1 个集合并且由用户创建。数据库的粗略规模:

  • 产品:52.000.000
  • 收藏:9.000.000
  • 用户:大约 9.000.000

我正在尝试检索用户拥有的产品+集合的数量,以及每个集合中的产品数量(该信息应该在所有 x 天生成并在 ElasticSearch 中编入索引)。

对于用户查询,我目前正在做这样的事情:

      SELECT
        users.*,
        (SELECT
          count(*)
        FROM
          products product
        WHERE
          product.user_id = user.id
        ) AS product_count,
        (SELECT
          count(*)
        FROM
          collections collection
        WHERE
          collection.user_id = user.id
        ) AS collection_count
      FROM
        users user
Run Code Online (Sandbox Code Playgroud)

所有 *_id 字段都已编入索引。使用解释(分析,详细)(删除敏感信息):

 Limit  (cost=0.00..156500.97 rows=100 width=41) (actual time=0.064..28345.363 rows=100 loops=1)
   Output: (...), ((SubPlan 1)), ((SubPlan 2))
   ->  Seq Scan on public.users user  (cost=0.00..14549429167.11 rows=9296702 width=41) (actual time=0.064..28345.241 rows=100 loops=1)
         Output: (...), (SubPlan 1), (SubPlan 2)
         SubPlan 1 …
Run Code Online (Sandbox Code Playgroud)

postgresql performance index count postgresql-performance

4
推荐指数
1
解决办法
3691
查看次数

函数中的 Postgres 真空

谷歌搜索后,很明显你不能从函数运行真空:

Postgres 邮件 - plpgsql 函数中的真空行为

由于内存管理限制,您无法从函数内部运行 VACUUM。在当前来源中有一个错误检查以防止您尝试。

Stackoverflow - 无法从函数或多命令字符串执行 VACUUM

加载数据后,我想对受影响的表进行“真空分析”,既要从已删除的记录中恢复空间,又要准确反映新内容。[...] 当我运行这个时,我得到:

ERROR: VACUUM cannot be executed from a function or multi-command string

但是我真的需要在运行某个函数时“自动”运行vacuum:这个函数更新了很多记录(如果不是全部),所以死行的数量增加得非常快,其他查询性能下降很多。问题是该函数是从另一个程序调用的。任何最佳实践?我应该在函数执行后手动将真空语句添加到一段单独的代码中,就像

sql = SELECT my_function() <program.execute(sql)> sql = VACUUM [FULL | ANALYZE] my_updated_table <program.execute(sql)>

postgresql performance vacuum postgresql-performance

4
推荐指数
1
解决办法
4388
查看次数

分析 PostgreSQL 的内存使用情况——为什么它一直在增长?

我将数百万行插入 PostgreSQL 9.5 数据库并观察到内存使用量的持续增长。由于表不是那么大,并且执行的操作(插入触发 Pl/Python 函数)不应该那么昂贵,我想知道为什么会发生这种情况。

目前 PostgreSQL 使用了大约 50 GB 的总可用空间 60 GB。我想了解 PostgreSQL 如何使用这 50 GB,尤其是因为我担心该进程会耗尽内存。

[更新] 今晚 PostgreSQL 内存不足,被操作系统杀死。

$ pg_top
last pid: 13535;  load avg:  1.26,  1.41,  1.42;       up 2+02:57:11                                                                                                                                                                19:29:26
3 processes: 1 running, 2 sleeping
CPU states: 12.4% user,  0.0% nice,  0.1% system, 87.4% idle,  0.0% iowait
Memory: 63G used, 319M free, 192M buffers, 28G cached
DB activity:   2 tps,  0 rollbs/s,   0 buffer r/s, 100 hit%,     42 row r/s,    0 row w/s 
DB …
Run Code Online (Sandbox Code Playgroud)

postgresql performance memory postgresql-performance

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

在没有表级锁的情况下在 postgresql 中添加具有默认值的列

有这样的问题 - 超过 2000 万行的表。

当我使用默认值添加新列时 - postgresql 锁定表超过 40 分钟,因此我的应用程序此时停止工作。

所以代替

ALTER TABLE "test" ADD COLUMN "field" boolean DEFAULT True NOT NULL;
Run Code Online (Sandbox Code Playgroud)

我愿意

ALTER TABLE "test" ADD COLUMN "field" boolean NULL;
ALTER TABLE "test" ALTER COLUMN "field" SET DEFAULT true;
Run Code Online (Sandbox Code Playgroud)

之后每个新行默认为 true,所以现在我需要更新 2000 万个当前行。我分批更新它们:

WITH cte AS (
SELECT id as pk
FROM "test"
WHERE  "field" is null
LIMIT  10000
)
UPDATE "test" table_
SET "field" = true
FROM   cte
WHERE  table_.id = cte.pk
Run Code Online (Sandbox Code Playgroud)

之后我做

ALTER TABLE "test" ALTER …
Run Code Online (Sandbox Code Playgroud)

postgresql performance alter-table postgresql-performance

4
推荐指数
1
解决办法
7593
查看次数

Postgres - 执行 VACUUM 需要多少空间

我知道在表上执行 VACUUM FULL 将释放磁盘空间并将其返回给操作系统。

有几次我的操作系统(Windows)警告我它的磁盘空间不足。我的反应是迅速关闭我所能做的一切,并在其中一个更活跃的表上运行 VACUUM FULL。

我注意到 VACUUM FULL 似乎需要至少几百 MB 的空闲空间才能实际工作。如果我在只有 50 MB 的磁盘空间时尝试在 1GB 的表上执行 VACCUM FULL,那么这很快就会消失,我的计算机很快就会停止,而 VACUUM FULL 将无法工作。

当我知道有未使用的空间可用但没有足够的空间来运行 VACUUM 时,如何释放 POSTGRES 数据库中的操作系统空间?

(我知道正确的答案是——“不要傻到一开始就让它发生”,但 sh1t 偶尔会发生!)

postgresql performance postgresql-performance

4
推荐指数
1
解决办法
1611
查看次数