标签: postgresql-performance

PostgreSQL 似乎在简单的条件连接中创建了低效的计划

考虑这两个查询:

SELECT
    t1.id, *
FROM
    t1
INNER JOIN
    t2 ON t1.id = t2.id
    where t1.id > -9223372036513411363;
Run Code Online (Sandbox Code Playgroud)

和:

SELECT
    t1.id, *
FROM
    t1
INNER JOIN
    t2 ON t1.id = t2.id
    where t1.id > -9223372036513411363 and t2.id > -9223372036513411363;
Run Code Online (Sandbox Code Playgroud)

注意:不是-9223372036513411363表中的最小值,并且条件将结果(从总行数 3.5 亿行)减少到 1700 万行。

就我个人而言,我希望 PostgreSQL 能够为这两个查询提供相同的计划,因为t1.id = t2.id自动意味着第二个条件。但不幸的是,PostgreSQL 正在创建两个不同的计划,第二个计划要好得多:

我非常喜欢第一个查询,因为我想从连接创建一个视图,并将 where 条件放在视图上的查询上,我在其中看到单个 id 列(我使用连接,USING因此单个 id 列在视图中可见) 。另外,我将连接两个以上的表,并且我不希望为每个连接添加这样的条件。

这种行为有什么原因吗?或者这是一个错误?有什么解决方法吗?

  • 替换ON …

postgresql performance join execution-plan postgresql-9.3 postgresql-performance

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

PostgreSQL 高磁盘 I/O

我正在评估 PostgreSQL 作为 Oracle 的替代品。我有一个包含 533 个表的数据库,其中最多包含 250,000 个条目。

\n\n

为了进行性能比较,我在 Oracle 和 PostgreSQL 上构建了数据库。

\n\n

然而,PostgreSQL 速度慢得多,并且它在 RAM 中存储的内容不多,而是具有大量的磁盘 I/O。

\n\n

我的性能测试:

\n\n
    \n
  • 将 50,000 个条目插入大约 250 列的表中
  • \n
  • 选择所有这些,包括不同表上的联接
  • \n
  • 更新附加“A”的字符串字段
  • \n
  • 删除引用表中的条目,这会导致所有条目被删除(在删除级联上)
  • \n
\n\n

我的系统配置:

\n\n
    \n
  • Windows 7、2 Xeons \xc3\xa0 8 核、32GB RAM、256GB SSD
  • \n
  • PostgreSQL 9.6
  • \n
  • 甲骨文 XE 11
  • \n
  • 玛丽亚数据库 10.2
  • \n
\n\n

以下是我测量的性能(5 次运行的平均值):

\n\n

比较

\n\n

NoTriggers 版本以ALTER TABLE x DISABLE ALL TRIGGERS.

\n\n

从图表中可以看出,PostgreSQL 并没有真正使用可用的 ram。\n查看资源监视器,它确实使用了高磁盘 io:

\n\n …

postgresql performance performance-testing postgresql-performance

5
推荐指数
0
解决办法
3758
查看次数

在冲突时更新具有相同值的目标列对性能的影响

这是一个关于 Postgres (v10) 的内部工作原理和性能的问题。

给定一个表 ,在和列github_repos上具有多列唯一索引,下面的两个批量更新插入操作之间是否存在任何性能差异(或其他需要注意的问题)?不同之处在于,在第一个查询中,和列包含在 UPDATE 中,而在第二个查询中则不包含。由于 UPDATE 在冲突时运行,因此和的更新值将与旧值相同,但这些列包含在 UPDATE 中,因为我正在使用的底层库就是这样设计的。我想知道按原样使用是否安全,或者我是否应该在更新中明确排除这些列。org_idgithub_idorg_idgithub_idorg_idgithub_id

查询#1:

INSERT INTO "github_repos" ("org_id","github_id","name")
VALUES (1,1,'foo')
ON CONFLICT (org_id, github_id)
DO UPDATE SET "org_id"=EXCLUDED."org_id","github_id"=EXCLUDED."github_id","name"=EXCLUDED."name"
RETURNING "id"
Run Code Online (Sandbox Code Playgroud)

查询#2:

INSERT INTO "github_repos" ("org_id","github_id","name")
VALUES (1,1,'foo')
ON CONFLICT (org_id, github_id)
DO UPDATE SET "name"=EXCLUDED."name"
RETURNING "id"
Run Code Online (Sandbox Code Playgroud)

github_repos桌子:

      Column       |       Type        | Collation | Nullable 
-------------------+-------------------+-----------+----------+
 id                | bigint            |           | not null |
 org_id            | bigint            |           | not null | …
Run Code Online (Sandbox Code Playgroud)

postgresql performance postgresql-performance

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

解决 PostgreSQL INSERT 性能不佳问题的系统配置

问题症状

postmaster与尝试插入低容量行的客户端连接相关的子进程的 CPU 使用率较高(导致插入的行比使用相同行慢 25 倍)。COPY ... FROM STDIN

背景

尝试识别系统/数据库配置以缓解上述较差的插入性能。我正在使用多线程 R 脚本来处理数据并将结果插入到 PostgreSQL 数据库中。我对 R 脚本进行了分析,以隔离调用的性能瓶颈DBI::dbBind(),同时用于top监视postmaster与子 R 线程打开的连接关联的子进程(请参阅下面的代码)。在 INSERT 期间,R 子进程大部分时间处于空闲状态(大概是在等待调用返回DBI::dbBind()),而postmaster子进程在其运行大约 2-3 分钟的时间内消耗了 95-100% 的 CPU。

系统/环境:

  • postgresql 版本 10.3(Fedora 包 10.3-5.fc27)
  • uname -a:Linux localhost 4.16.6-202.fc27.x86-64 #1 SMP Wed May 2 00:09:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
  • /proc/cpuinfo: 16 个处理器 ( Intel(R) Xeon(R) CPU D-1541 @ 2.10GHz)
  • ulimit …

postgresql performance configuration r postgresql-10 postgresql-performance

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

未使用时间戳列上的 Postgres 索引

我有一个数据库,其中有一列名为timestamptype timestamp without timezone,该列上有一个 btree 索引。

我有一个查询如下

SELECT
   *
FROM
  employee 
WHERE 
  timestamp >= timestamp '2020-01-27 13:24:09'
Run Code Online (Sandbox Code Playgroud)

timestamp但是,解释分析显示未使用该列上的索引:

Seq Scan on employee  (cost=0.00..5498.73 rows=34377 width=381) (actual time=0.016..37.944 rows=34251 loops=1)
   Filter: ("timestamp" >= '2020-01-27 13:24:09'::timestamp without time zone)
   Rows Removed by Filter: 21167
 Planning Time: 0.255 ms
 Execution Time: 40.277 ms
Run Code Online (Sandbox Code Playgroud)

如果我使用包含时间戳的过滤条件更改查询,而不是1 month1 year如上所述),则使用列上的索引。

Bitmap Heap Scan on employee  (cost=59.51..4510.25 rows=2996 width=381) (actual time=2.164..5.204 rows=2958 loops=1)
   Recheck Cond: ("timestamp" >= '2020-12-27 13:24:09'::timestamp without …
Run Code Online (Sandbox Code Playgroud)

postgresql index index-tuning postgresql-performance

5
推荐指数
0
解决办法
2609
查看次数

PostgreSql 在运行时更改相同的查询计划

我这里有一个非常奇怪的问题。我们的搜索查询接收多个参数并通过不同表中的多个联接进行搜索。查询在我们运行的前几次运行良好,然后有时会严重减慢,例如:从 200 毫秒到 15000/20000 毫秒。在同一个查询上。

最初我认为这是后端 ORM 问题,但在彻底检查并打开慢速查询日志、打开 auto_explain 功能后,我意识到查询计划在几次调用后发生了变化。我们在后端放置一个循环,在同一线程上多次执行查询(用于测试),我发现几乎总是在执行 8 次后数据库开始记录慢速查询。最后结果是查询计划发生了变化。最重要的变化是(我认为)TimeSlots 表上的变化,从 seq 扫描到位图索引扫描,它估计的行数比表中的行数少得多。估计:566 实际:100 000 左右。

我之前尝试过的事情:

  • 将硬件从 2 核 6GB 升级到 8 核 26GB 内存(100GB SSD)
  • 禁用任何其他应用程序(从而停止任何其他负载)访问它。
  • 在表上执行手动(也有自动运行的作业)VACUUM、ANALYZE、REINDEX。
  • 设置各个列的统计信息,例如SlotDateTime(至10000)
  • 创建不明确的统计数据。
  • 增加了 work_mem、maintenance_work_mem、shared_buffers 大小。
  • 将 seq_page_cost 减少到 1。

这是选择语句:

SELECT DISTINCT u."UserId"     AS                                     UserId,
                             cast(cuj.company_id as bigint) AS                                     CompanyId,
                         cast(ts.SlotsCount as bigint) as SlotsCount,
                         case when cuj.vip is null then false else cuj.vip end vip,
                         u.is_vip       as                                     userVip,

                         case
                             when ts2.EarliestDate isnull then '7777-12-01 21:00:00.000000'
                             else ts2.EarliestDate …
Run Code Online (Sandbox Code Playgroud)

postgresql execution-plan postgresql-performance

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

为什么 COALESCE 会阻止在 varchar 上使用索引,但不会阻止在文本列上使用索引?

想象一个视图,其中包含来自两个不同表的COALESCEvarchar列。

底层证券varchars在两个表中都有索引。

在 Postgres 11.6 中,根据结果过滤此视图COALESCE不使用索引,而是进行表扫描。

但是,如果我将列更改为text,在同一列上过滤完全相同的视图,则索引将按您的预期使用。

例子

假设我有一个一些标识符随时间变化的测量值表。还有一个几乎相同的表,其中包含估计值:

CREATE TABLE measured (
  id int,
  ts timestamp,
  identifier character varying,
  measured_value int
);
CREATE INDEX ON measured(identifier);

CREATE TABLE estimated (
  id int,
  ts timestamp,
  identifier character varying,
  estimated_value int
);
CREATE INDEX ON estimated(identifier);
Run Code Online (Sandbox Code Playgroud)

每个表有 100 万行数据:

INSERT INTO measured
SELECT
    generate_series(1, 1000000),
    to_timestamp((random() * 100000)::int),
    left(md5(random()::text), 2),
    random() * 10;

INSERT INTO estimated
SELECT
    generate_series(1, 1000000),
    to_timestamp((random() * …
Run Code Online (Sandbox Code Playgroud)

postgresql varchar execution-plan index-tuning postgresql-performance

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

优化匹配数组前 N 项的查询

我现在正在使用充满国际象棋游戏数据的 Postgres 数据库,其中每个游戏都是“记录”表中的一行。玩家的动作和这些动作的(可选)计算机评估都有自己的列并存储为数组。

我编写了一个查询来检索指定的开局动作序列的所有评估。(你可能认为计算机的评估会是一致的 - 但事实并非如此。)开局序列的长度是任意的 - 可以是一步,也可以是三十步。

下面是一个示例查询,它查找以相同的十步开局序列开始的所有游戏,然后对于每个带有评估的游戏,返回计算机对游戏中该点的评估 -

SELECT evaluation[10]
FROM records
WHERE moves[1:10]::text[] = ARRAY['b4', 'e5', 'Bb2', 'd6', 'Nf3', 'Nf6', 'g3', 'Bg4', 'Bg2', 'h5']::text[]
AND evaluation IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)

我不确定它是否相关,但移动数据始终是 2-6 个字符的字母数字字符串,并且计算机评估大部分是小数(正数和负数),但确实包括偶尔的特殊字符(强制将死者有一个 octothorpe前缀)。

这是表描述的相关片段 -

     Column      |              Type              | 
-----------------+--------------------------------+-
 id              | bigint                         | 
 moves           | character varying(255)[]       |  
 evaluation      | character varying(255)[]       | 
    "records_pkey" PRIMARY KEY, btree (id)
Access method: heap
Run Code Online (Sandbox Code Playgroud)

这是来自 EXPLAIN ANALYZE 的查询计划:

 Gather  (cost=1000.00..736354.70 rows=905 width=516) (actual time=28251.267..28253.139 rows=0 loops=1)
   Workers Planned: 2 …
Run Code Online (Sandbox Code Playgroud)

postgresql index optimization array postgresql-performance

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

PostgreSQL 忽略索引,运行 seq 扫描

我的表包含列的索引total_balance

\d balances_snapshots
                                          Table "public.balances_snapshots"
    Column     |            Type             | Collation | Nullable |                    Default
---------------+-----------------------------+-----------+----------+------------------------------------------------
 user_id       | integer                     |           |          |
 asset_id      | text                        |           |          |
 timestamp     | timestamp without time zone |           |          | now()
 total_balance | numeric                     |           | not null |
 id            | integer                     |           | not null | nextval('balances_snapshots_id_seq'::regclass)
Indexes:
    "balances_snapshots_pkey" PRIMARY KEY, btree (id)
    "balances_snapshots_asset_id_idx" btree (asset_id)
    "balances_snapshots_timestamp_idx" btree ("timestamp")
    "balances_snapshots_user_id_idx" btree (user_id)
    "balances_total_balance_idx" btree (total_balance)
Foreign-key constraints:
    "balances_snapshots_asset_id_fkey" FOREIGN KEY (asset_id) …
Run Code Online (Sandbox Code Playgroud)

postgresql index datatypes postgresql-performance

5
推荐指数
2
解决办法
1603
查看次数

数组字段上的 btree 索引实际上有什么作用吗?

在PG中你可以创建一个像这样的表

CREATE TABLE foo (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid (),
  name text NOT NULL,
  things text[] NOT NULL DEFAULT ARRAY[] ::text[]
)
Run Code Online (Sandbox Code Playgroud)

以及相关索引

CREATE INDEX foo_text ON foo USING btree (name, things);
Run Code Online (Sandbox Code Playgroud)

但很难找到有关其作用的信息。我继承了一个像这样的表(数亿行,尽管这个数组几乎总是有 0 或 1 个条目),并且索引确实在 pg_stat_all_indexes 中偶尔命中,所以至少在某些情况下可以发生了,但我也注意到,相对于其他索引,该索引占用了大量空间,并且清理速度要慢得多。 PG 中数组字段的索引有意义吗?btree

如果目标是能够找到things包含所提供的一个或多个值的行,是否有更好的方案?(假设我们此时无法将其正确规范化为它自己的表。)

我们期望查询会命中该索引,如下所示

SELECT id FROM foo
WHERE name = $1
AND $2::text = ANY(things)
Run Code Online (Sandbox Code Playgroud)
SELECT id FROM FOO
WHERE name = $1
AND things @> $2::text[]
Run Code Online (Sandbox Code Playgroud)

postgresql index array postgresql-performance

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