标签: postgresql-performance

调整设置以减少 postgres 中大型查询的读取块数

使用 postgres 9.6,我不明白共享缓冲区如何与索引一起工作。

设置

  • Postgres 9.6
  • 所有默认设置
    • 共享缓冲区:128Mb
    • 工作内存:4Mb
    • 块大小:8192
    • ...

这意味着 shared_buffer 大小为 128 * 1024 * 1024 / 8192 = 16384 个块。

测试数据

我创建了一个简单的表,其中包含随机数据和每列的索引。

DROP TABLE IF EXISTS sandbox;


CREATE TABLE sandbox AS
SELECT generate_series(1, 4000000) AS pk,
       random() AS x;

CREATE INDEX ON sandbox(pk);
CREATE INDEX ON sandbox(x);
Run Code Online (Sandbox Code Playgroud)

我去了 4M 行。这是表和索引占用的大小:

postgres=# SELECT relname AS "relation",
       pg_relation_size(C.oid) / 8192 AS "blocks",
       pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE relname …
Run Code Online (Sandbox Code Playgroud)

postgresql performance postgresql-performance

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

你能减慢对 postgres 数据库中特定用户的查询吗

我假设可以减慢 postgres 数据库中特定用户的查询访问速度。你会怎么做?有没有办法让用户看到这样的设置已经被放置在他们身上,以及用户可以做些什么来克服它,如果有的话。

基本上我有兴趣在每个用户的基础上限制资源以防止不良行为者滥用系统。

postgresql performance postgresql-performance

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

如何加快查询时间序列中的最后一个值?

prices在 PostgreSQL 10 DB 中有一个时间序列表。
这是一个简化的测试用例来说明问题:

CREATE TABLE prices (
    currency text NOT NULL,
    side     boolean NOT NULL,
    price    numeric NOT NULL,
    ts       timestamptz NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

我想快速查询每个currency/side双人组的最后一个值,因为这会给我每种货币的当前买入/卖出价格。

我目前的解决方案是:

create index on prices (currency, side, ts desc);

select distinct on (currency, side) *
 order by currency, side, ts desc;
Run Code Online (Sandbox Code Playgroud)

但这会让我在这个只有 ~30k 行的表中查询非常(~500ms)。

实际的表都有,我想组四列而不是两个。下面是实际的表和查询的样子:

create table prices (
    exchange integer not null,
    pair text not null,
    side …
Run Code Online (Sandbox Code Playgroud)

postgresql performance index-tuning greatest-n-per-group postgresql-10 postgresql-performance

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

加入联结表以实现高效排序/分页的推荐方法是什么?

简介: 我有一个简单的数据库模式,但即使只有几十条记录,基本查询的性能也已经成为一个问题。

数据库:PostgreSQL 9.6

简化架构

CREATE TABLE article (
  id bigint PRIMARY KEY,
  title text NOT NULL,
  score int NOT NULL
);
CREATE TABLE tag (
  id bigint PRIMARY KEY,
  name text NOT NULL
);
CREATE TABLE article_tag (
  article_id bigint NOT NULL REFERENCES article (id),
  tag_id bigint NOT NULL REFERENCES tag (id),
  PRIMARY KEY (article_id, tag_id)
);
CREATE INDEX ON article (score);
Run Code Online (Sandbox Code Playgroud)

生产数据信息

所有表都是读/写的。写入量低,每几分钟左右只有一个新记录。

大概记录数:

  • ~66K 篇文章
  • ~63K 标签
  • ~147K article_tags

每篇文章平均 5 个标签。

问题 …

postgresql performance join paging postgresql-performance

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

Postgresql 无法使用我的覆盖索引并退回到更慢的位图扫描

我试图弄清楚为什么我的表在索引扫描速度非常快时使用位图堆扫描。

桌子:

webarchive=# \d web_pages
                                               Table "public.web_pages"
      Column       |            Type             |                              Modifiers
-------------------+-----------------------------+---------------------------------------------------------------------
 id                | bigint                      | not null default nextval('web_pages_id_seq'::regclass)
 state             | dlstate_enum                | not null
 errno             | integer                     |
 url               | text                        | not null
 starturl          | text                        | not null
 netloc            | text                        | not null
 file              | bigint                      |
 priority          | integer                     | not null
 distance          | integer                     | not null
 is_text           | boolean                     |
 limit_netloc      | boolean                     |
 title             | citext                      |
 mimetype          | text …
Run Code Online (Sandbox Code Playgroud)

postgresql performance postgresql-9.6 postgresql-performance

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

可扩展查询前 x 天内的事件运行计数

我已经在stackoverflow上发布了这个问题,但我想我可能会在这里得到更好的答案。
我有一个表存储用户发生的数百万个事件:

                                       Table "public.events"
   Column   |           Type           |                         Modifiers                         
------------+--------------------------+-----------------------------------------------------------
 event_id   | integer                  | not null default nextval('events_event_id_seq'::regclass)
 user_id    | bigint                   | 
 event_type | integer                  | 
 ts         | timestamp with time zone | 
Run Code Online (Sandbox Code Playgroud)

event_type 有 5 个不同的值、数百万用户以及每个用户每个 event_type 的不同事件数,通常范围为 1 到 50。

数据样本:

+-----------+----------+-------------+----------------------------+
| event_id  | user_id  | event_type  |         timestamp          |
+-----------+----------+-------------+----------------------------+
|        1  |       1  |          1  | January, 01 2015 00:00:00  |
|        2  |       1  |          1  | January, 10 2015 00:00:00  | …
Run Code Online (Sandbox Code Playgroud)

postgresql performance scalability window-functions postgresql-performance

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

为什么 10,000 个 ID 的列表比使用等效的 SQL 来选择它们的性能更好?

我有一个带有遗留查询的 Rails 应用程序,我想对其进行翻新。当前实现执行两个 SQL 查询:一个获取大量 ID,第二个查询使用这些 ID 并应用一些额外的连接和过滤器来获得所需的结果。

我试图用避免往返的单个查询替换它,但这样做会导致我的本地测试环境(这是完整生产数据集的副本)的性能大幅下降。新查询中似乎没有使用索引,导致全表扫描。我曾希望单个查询能够保持与原始代码相同的性能,理想情况下,由于不需要发送所有 ID,因此可以对其进行改进

这是我实际问题的最小化版本。稍大一点的版本在讨论为什么10000个ID的列表中一个复杂的查询有更好的表现与多个热膨胀系数相比,相当于SQL选择它们?.

当前查询

有一个查询需要大约 6.5 秒来计算 10000 多个 ID 的列表。您可以visible_projects在下面的“建议查询”部分中将其视为 CTE 。然后将这些 ID 输入到此查询中:

EXPLAIN (ANALYZE, BUFFERS)
WITH visible_projects AS NOT MATERIALIZED (
    SELECT
        id
    FROM
        "projects"
    WHERE
        "projects"."id" IN (
            -- 10000+ IDs removed
)),
visible_tasks AS MATERIALIZED (
    SELECT
        tasks.id
    FROM
        tasks
    WHERE
        tasks.project_id IN (
            SELECT
                id
            FROM
                visible_projects))
SELECT
    COUNT(1)
FROM
    visible_tasks;
Run Code Online (Sandbox Code Playgroud)

查询计划(depesz

Aggregate  (cost=1309912.31..1309912.32 rows=1 width=8) (actual time=148.661..153.739 …
Run Code Online (Sandbox Code Playgroud)

postgresql performance query-performance postgresql-performance

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

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
查看次数