【问题标题】:How to fix this slow Postgres select query如何修复这个缓慢的 Postgres 选择查询
【发布时间】:2020-08-27 11:02:33
【问题描述】:

我需要一点关于 PostgreSQL 查询的帮助。我有以下 SELECT 查询,它需要大约 30 秒才能在包含大约 100.000 和 200.000 个条目的表上运行。

SELECT i.id, i.debit_nr, i.pat_id, i.pat_name, i.invoice_id, i.invoice_date, i.due_date, i.client_short, i.payment, i.payment_option, i.marker, i.comment, sum(t.Sum) AS i_sum, i.import_date 
FROM invoices AS i 
   LEFT JOIN invoice_items AS t ON t.invoice_id = i.id 
   JOIN jobs AS j ON i.job_id = j.id 
GROUP BY i.id

我发现似乎很慢的部分只是发票表上的 SELECT,因为如果我运行

SELECT i.id, i.debit_nr, i.pat_id, i.pat_name, i.invoice_id, i.invoice_date, 
i.due_date, i.client_short, i.payment, i.payment_option, i.marker, i.comment, i.import_date 
FROM invoices AS i

需要几乎相同的时间。

GroupAggregate  (cost=63048.71..65737.16 rows=110203 width=76) (actual time=1421.792..1785.528 rows=110203 loops=1)
  Group Key: i.id
  ->  Sort  (cost=63048.71..63577.52 rows=211523 width=76) (actual time=1421.772..1573.998 rows=211527 loops=1)
        Sort Key: i.id
        Sort Method: external merge  Disk: 19944kB
        ->  Hash Right Join  (cost=24793.35..34938.02 rows=211523 width=76) (actual time=473.877..1010.362 rows=211527 loops=1)
              Hash Cond: (t.invoice_id = i.id)
              ->  Seq Scan on invoice_items t  (cost=0.00..3878.23 rows=211523 width=12) (actual time=0.035..112.034 rows=211523 loops=1)
              ->  Hash  (cost=22123.81..22123.81 rows=110203 width=72) (actual time=472.566..472.566 rows=110203 loops=1)
                    Buckets: 65536  Batches: 4  Memory Usage: 3592kB
                    ->  Hash Join  (cost=777.49..22123.81 rows=110203 width=72) (actual time=7.784..334.883 rows=110203 loops=1)
                          Hash Cond: (i.job_id = j.id)
                          ->  Seq Scan on invoices i  (cost=0.00..19831.03 rows=110203 width=76) (actual time=0.005..170.120 rows=110203 loops=1)
                          ->  Hash  (cost=705.55..705.55 rows=5755 width=8) (actual time=7.707..7.707 rows=5755 loops=1)
                                Buckets: 8192  Batches: 1  Memory Usage: 289kB
                                ->  Seq Scan on jobs j  (cost=0.00..705.55 rows=5755 width=8) (actual time=0.004..4.741 rows=5755 loops=1)
Planning time: 0.874 ms
Execution time: 1824.846 ms

问题是,我是否在 id 字段或此选择中需要的所有字段上添加索引都没关系。

如何加快速度?

PS:它是 Windows 服务器上的 PostgreSQL 9.0。

【问题讨论】:

  • 与您的问题无关,但是:Postgres 9.0 已经end-of-life 五年了。您确实应该尽快计划升级到当前(和维护的)版本。
  • “排序方法:外部合并磁盘”大约需要半秒。您可以通过增加work_mem 来避免这种情况——发票上的 Seq 扫描只需要 170 毫秒
  • "运行大约需要 30 秒" - 不,它不需要。执行计划清楚地表明它只需要大约 2 秒。 28 秒的差异是由于通过网络发送行以及您的应用程序或 SQL 客户端需要处理(并可能显示)110203 行的时间造成的。
  • pgAdmin 在显示大型结果时会非常慢。但是你为什么要显示超过 100000 行呢?你真的打算逐一阅读吗?
  • 那么是您的应用程序需要 30 秒来接收和处理这 100000 行。

标签: sql postgresql query-performance pgadmin postgresql-9.0


【解决方案1】:

尝试使用相关子查询编写查询:

SELECT i.*,
       (SELECT SUM(it.Sum) 
        FROM invoice_items it
        WHERE it.invoice_id = i.id
       ) as i_sum
FROM invoices i ;

避免外部聚合可能有助于提高性能(尽管 Postgres 有一个很好的优化器,所以这并不总是正确的。你希望在invoice-items, invoice_id, sum. I left jobs 上的索引中排除查询,因为它没有好像被使用了。

【讨论】:

  • 我尝试了您的查询,但花费了相同的时间...如上所述,我发现如果我只在发票表上进行选择,而没有加入。在这种情况下你是对的,因为这是一个查询,它是由不同的搜索参数构建的,这些参数可能会影响工作,但是对于一个操作,我需要所有发票以及上面显示的查询等项目的总和。
  • @pyr0t0n 。 . .您的问题似乎是您从 invoices 返回的数据量,而不是查询中发生的其他事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多