【问题标题】:PostgreSQL index not used after large inserts大插入后未使用 PostgreSQL 索引
【发布时间】:2020-03-27 10:07:17
【问题描述】:

我有一个需要处理“大量”数据的应用程序:第一步是从 CSV 文件(在所描述的情况下大约 170 万行)将数据临时加载到表中,第二步是处理更新/ 根据通过一个查询加载的数据在另一张表上插入:

UPDATE destination_table d
SET ...
FROM temp_table t
WHERE d.column = t.column;

注意:temp_table 在整个过程完成后被清空

我们遇到了一些性能问题,因为 t.column 上没有索引(postgres 进程正在使用 100% 的 CPU,查询可能会卡住几个小时甚至几天),我们添加了它并且查询是“仅”在我们的环境中运行大约 5 分钟,这是完全可以接受的。

我面临的问题是在客户端环境中(相同的 RAM / vCPU 编号),索引似乎没有被使用。在其中一个中,应用程序似乎可以工作,但我们现在在同一个文件上面临同样的问题(查询卡住了几天,一个进程使用了​​ 100% 的 CPU)。

经过一番检查,我注意到索引没有在他们的环境中扫描

在我们的 pg_stat_all_indexes 告诉我这个索引:

  • idx_scan : 2060888
  • idx_tup_read : 3762435
  • idx_tup_fetch : 3762432

在他们的环境中:

  • idx_scan : 6
  • idx_tup_read : 6
  • idx_tup_fetch : 6

我已经和某人谈过了,他告诉我原因可能是插入后桌子没有被吸尘。一个进程已于 23/03 在他们的环境中启动(仍在“运行”...),当我查看 temp_table 上的 last_autovacuum 时,它已在 20/02(不是 03)完成,显然只有一次因为 autovacuum_count 是“1”。他告诉我,我们应该在利用过程中“强制”真空,但由于表中的插入和更新应该是连续的,我不明白它是如何工作的。

问题:

  • 每次我在我的 temp_table 中加载数据时是否必须进行真空(分析?),以便在执行以下更新时正确使用我的索引?
  • 什么可以解释环境之间的索引扫描差异?

【问题讨论】:

  • 应该更专注
  • 什么意思?
  • 你应该说清楚你想要什么
  • 已编辑,看起来更清晰了吗?
  • 是的,如果您希望在批量更改后立即获得准确的统计信息,则在批量更改/加载表(临时或非临时)后需要 analyze

标签: postgresql indexing insert


【解决方案1】:

当我查看 temp_table 上的 last_autovacuum 时,它已在 20/02(不是 03)完成,显然只有一次,因为 autovacuum_count 为“1”。

我认为临时表从未被自动清空。这是一个实际的 TEMP 表,还是您手动从中删除行的永久表?

他告诉我,我们应该在利用过程中“强制”真空,但由于表中的插入和更新应该是连续的,我不明白它是如何工作的。

我不明白这个问题。在 INSERT 和 UPDATE 语句之间插入 VACUUM ANALYZE temp_table 语句。 (或者可能只是一个分析)。

每次我在 temp_table 中加载数据时都必须进行真空(分析?),以便在执行以下更新时正确使用我的索引?

是的,如果您希望使用正确的统计信息来计划查询,则必须执行 ANALYZE。当然,这并不能保证它会使用您想要的计划。

什么可以解释环境之间的索引扫描差异?

可能是上述情况,但在不使用索引时查看“EXPLAIN (ANALYZE, BUFFERS)”的输出肯定有助于确定它。

【讨论】:

  • 1.要明确:这不是一个真正的临时表,而是一个“普通”表,其中临时存储数据 2。我也不知道,这就是我问的原因,他的句子是“不要运行它(真空分析)代码本身。它永远不会结束:这更像是一个利用过程” 3. 好的,所以我想我还是会尝试这样做 4. 解释可能有点复杂,因为实际上在一个事务中启动了多个查询在我流程的所谓“第二部分”中,但始终是这个特定的更新(与索引使用相关的更新)卡住了。
猜你喜欢
  • 1970-01-01
  • 2022-08-21
  • 1970-01-01
  • 1970-01-01
  • 2020-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多