标签: postgresql-performance

RDS 上非常慢的简单 PostgreSQL 查询

我似乎在中型 RDS 盒子(db.m3.medium,3.7gb ram)上的查询速度很慢。

这是一个包含 4,152,928 行的表格。

select sum(some_field) c
from pages
where pages.some_id=123
and pages.first_action_at > '2014-01-01 00:00:00 +1000'
Run Code Online (Sandbox Code Playgroud)

总运行时间:45031 毫秒。
在本地,我有大约 110 万行,同样的查询需要大约 450 毫秒。

这是查询计划,来自解释:

Aggregate  (cost=475640.59..475640.60 rows=1 width=4)
   ->  Seq Scan on pages  (cost=0.00..475266.07 rows=149809 width=4)
         Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time zone) 
                AND (some_id = 447))
Run Code Online (Sandbox Code Playgroud)

这是来自解释分析的回应:

 Aggregate  (cost=475641.74..475641.76 rows=1 width=4) (actual time=42419.717..42419.718 rows=1 loops=1)
   ->  Seq Scan on pages  (cost=0.00..475267.22 rows=149810 width=4) (actual time=0.013..42265.908 rows=141559 loops=1)
    Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time …
Run Code Online (Sandbox Code Playgroud)

postgresql performance index index-tuning postgresql-performance

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

继承表和索引的性能问题

我有一个带有主表和 2 个子表的 PostgreSQL 数据库。我的主表:

CREATE TABLE test (
    id serial PRIMARY KEY, 
    date timestamp without time zone
);
CREATE INDEX ON test(date);
Run Code Online (Sandbox Code Playgroud)

我的子表:

CREATE TABLE test_20150812 (
    CHECK ( date >= DATE '2015-08-12' AND date < DATE '2015-08-13' )
) INHERITS (test);

CREATE TABLE test_20150811 (
    CHECK ( date >= DATE '2015-08-11' AND date < DATE '2015-08-12' )
) INHERITS (test);

CREATE INDEX ON test_20150812(date);
CREATE INDEX ON test_20150811(date);
Run Code Online (Sandbox Code Playgroud)

当我执行查询时:

select * from test_20150812 where date > '2015-08-12' order …
Run Code Online (Sandbox Code Playgroud)

postgresql performance index partitioning inheritance postgresql-performance

7
推荐指数
1
解决办法
4217
查看次数

当没有结果并且指定了 LIMIT 时,SELECT 非常慢

我遇到了一个问题,SELECT查询很慢,因为当最终结果的数量为 0并且LIMIT指定了一个子句时,它不使用索引。

如果结果数大于 0,则 Postgres 使用索引并在 ~ 1ms 内返回结果。据我所知,这似乎总是正确的。

如果结果数为 0 且没有LIMIT使用,则 Postgres 使用索引,结果在 ~ 1ms 内返回

如果结果数为 0 并且LIMIT指定了 a,则 Postgres 会执行顺序扫描,结果大约需要 13,000 毫秒。

为什么 PostgreSQL 在最后一种情况下不使用索引?

基数:

总计约 2100 万行。
~ 300 万行WHERE related_id=1
~ 300 万行WHERE related_id=1 AND platform=p1
2 行WHERE related_id=1 AND platform=p2
0 行WHERE related_id=1 AND platform=p3
~ 800 万行WHERE platform=p2

Postgres 版本:9.4.6

表架构:

CREATE TYPE platforms AS ENUM ('p1', …
Run Code Online (Sandbox Code Playgroud)

postgresql performance index statistics postgresql-9.4 postgresql-performance

7
推荐指数
1
解决办法
3075
查看次数

寻找更简单的递归查询替代方案

实际查询更多,但我面临的问题可以归结为:

用于过滤单调递增整数行集的查询,以便 -在最终结果集中, row(n+1).value >= row(n).value + 5

对于我需要解决的实际问题,行集计数在 1000 秒内。

举几个例子来澄清:

  • 如果行是: 1,2,3,4,5 :那么查询应该返回:1
  • 如果行是: 1,5,7,10,11,12,13 :那么查询应该返回:1,7,12
  • 如果行是:6,8,11,16,20,23:那么查询应该返回:6,11,16,23
  • 如果行是:6,8,12,16,20,23:那么查询应该返回:6,12,20

我设法通过以下查询获得了所需的结果,但它似乎过于复杂。取消注释不同的“..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)

postgresql performance cte recursive postgresql-performance

7
推荐指数
1
解决办法
2098
查看次数

postgres 查询性能:视图与函数

我有一个场景,我需要运行工资报告。该报告计算特定日期范围内按员工分组的工资金额。

例如,当运行 2016-11-01 到 2016-11-30 的报告时,我会看到以下结果:

Staff Id    Total
------------------
1           123.00
2           439.22
Run Code Online (Sandbox Code Playgroud)

我对上述报告使用以下查询:

select 
    user_id as staff_id,
    sum(amount) as total
from transaction
where
    business_id = <business_id> and
    type = 'staff' and
    kind = 'commission' and
    created_at between <start_date> and <end_date>
group by
    user_id;
Run Code Online (Sandbox Code Playgroud)

我正在尝试根据以下要求确定优化此查询性能的最佳方法:

  • 结果将根据business_idstart_dateend_date
  • 数据应该始终是新鲜的

看来视图和函数都可以完成这项工作,但我并不能 100% 确定哪种方法是考虑到需求的最佳方法。

旁注:如果能够根据上面提到的参数来缓存数据就太好了,但是数据库方面似乎没有很好的解决方案。如我错了请纠正我!

附加信息:

  • 我正在运行 Postgres 9.6
  • 我在表中的business_idtypekind和列上有索引。这些都是单列、btree 索引。user_idcreated_attransaction

postgresql performance postgresql-performance

7
推荐指数
1
解决办法
9946
查看次数

Postgres 在单个事务中在多个表中大量插入的成本

在单个事务的多个表中插入大量或行(数百万)所产生的额外成本是多少?

是否可以做一些事情(调整参数),以便在单个事务中大量插入的成本接近在自动提交中进行的成本?

postgresql performance postgresql-performance

7
推荐指数
2
解决办法
7659
查看次数

postgres; 索引会自动重新索引新数据吗?

如果我在 Postgres 表中有一堆行,然后创建一个索引,如果在创建后插入新数据行,索引是否会自动更新?

或者说,REINDEX 是仅在一些罕见的情况下需要,还是在添加新数据时才需要?

postgresql performance postgresql-performance

7
推荐指数
1
解决办法
5953
查看次数

100k DDL 语句上的 Postgres 事务 OOM

我们在 PostgreSQL 的单个事务中执行大约 100k DDL 语句。在执行过程中,各个 Postgres 连接的内存使用量逐渐增加,一旦它无法获得更多内存(在 3GB 内存上从 10MB 使用量增加到 2.2GB),OOM 杀手用 9 命中它,导致 Postgres 进入恢复模式.

BEGIN;

CREATE SCHEMA schema_1;
-- create table stmts - 714
-- alter table add pkey stmts - 714
-- alter table add constraint fkey stmts - 34
-- alter table add unique constraint stmts - 2
-- alter table alter column set default stmts - 9161
-- alter table alter column set not null stmts - 2405
-- alter table add check …
Run Code Online (Sandbox Code Playgroud)

postgresql performance transaction ddl postgresql-9.6 postgresql-performance

7
推荐指数
1
解决办法
347
查看次数

PostgreSQL 引用多个表最有效的方法

当一次只能进行一个引用时,我正在寻找在一个表中引用多个表的最有效方法。这意味着表 A 和 B 被表 C 引用,但 A 和 B 不能在 C 的一行中引用,并且我在编写查询时选择要查看的表。
我考虑过 4 种方法:

  • 有一个列type和一个列FK,这样我就可以进行像这样的连接type = 'A' AND a.pk = c.a_fk(这就是我们现在使用的)
  • 使用继承:A 和 B 都从“父”表继承序列,并且 C 具有“父”表的外键,但这在 PostgreSQL 中是不可能的
  • 使用与继承相同的原理,但使用另一个表 D。A 和 B 都有对 D 的引用,C 也有对 D 的引用,我可以像这样进行连接FROM c JOIN a ON a.d_fk = c.d_fk
  • 使用按表列我想要一个外键

在我尝试的每个解决方案中,查询规划器对于将返回多少行的判断都是错误的。
这是一个例子:我创建了一个简单的数据库,其中有 3 个表,如下所示:

                            Table "public.a"
 Column |  Type  | Collation | Nullable |            Default            
--------+--------+-----------+----------+-------------------------------
 pk     | bigint |           | not null | …
Run Code Online (Sandbox Code Playgroud)

postgresql performance database-design postgresql-9.6 postgresql-11 postgresql-performance

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

当 PostgreSQL 的“类别”太多时,我应该使用枚举吗?

问题

我计划将包含更多 1000 万条记录的 CSV 加载到 PostgreSQL v12.1,其中一列具有“分类”值,因此为其创建枚举类型似乎是一个不错的选择,但它包含 208 个类别。

最短的字段为 2,最长的字段为 11 个字符。所有字段的平均值为 2.4。字符编码是 UTF8,但所有字符都是 ASCII

问题:

我应该使用enumeratedvarchar哪种类型?

附加信息

我丢弃char是因为官方 PostgreSQL 文档说明了有关charvarchartext 的以下内容

提示:这三种类型之间没有性能差异,除了使用空白填充类型时增加了存储空间,以及在存储到长度受限列时需要额外的一些 CPU 周期来检查长度。虽然 character(n) 在其他一些数据库系统中具有性能优势,但在 PostgreSQL 中没有这样的优势;事实上 character(n) 通常是三个中最慢的,因为它有额外的存储成本。在大多数情况下,应改用文本或字符变化。

PostgreSQL 中的枚举值在磁盘上占用4 个字节(请参阅 8.7.4. 实现细节)。考虑到这一点和使用enum类型的2.4 平均字符串长度会导致磁盘使用率略高(PostgreSQL 中的短字符串需要一个额外的字节磁盘空间)。我仍然有一种直觉,即使用 enum 是更好的选择,因为它的实现使许多针对它的操作更快。

postgresql performance import postgresql-performance

7
推荐指数
2
解决办法
2577
查看次数