语句比平时慢250倍

Statement is 250 times slower than usual

我正在 运行宁一系列很长的陈述,移动大量数据。有问题的陈述看起来像这样:

CREATE TABLE a (...);
WITH cte_1 AS (...),
cte_2 AS (...)
INSERT INTO a (...)
SELECT ....

这将创建 table 并用大约 60 000 个大行填充它。通常执行此语句大约需要 1 秒。 "Usually" 表示完全相同的环境(所有 tables 和数据都是由脚本创建的 - 无需手动交互,因此在数据和数据结构方面,同一环境的所有实例都是相同的)但是在不同的 machine 上,只需 1 秒即可执行此操作。

但是在我的新 machine 上,这个语句突然需要 4.5 分钟才能完成。在那段时间里,Postgresql 占用了 CPU 核心的 100%。在那段时间里,如果我打开一个新的连接,比如说,与 DBeaver 和 运行 完全相同的查询,只需一个更改(创建 table b,然后插入,来自完全相同的数据源),在第一个查询 运行ning.

期间,需要 0.8 秒才能完成

所以这绝对不是脚本,而是关于 Postgresql 的内部工作或其配置的问题。这就是我分享它而不是代码的原因。

哦,还有这个查询:

SELECT 
  pid, datname, usename,
  application_name, query, state, 
  to_char(current_timestamp - query_start, 'HH24:MI:SS') AS running_for
FROM pg_stat_activity;

输出2个DBeaver进程(SHOW search_path空闲,上面的查询),慢查询:

9736 my_db my_user psql active 00:02:42

在数百个语句中,在各种模式中,具有各种复杂性,这是唯一受影响的语句。唯一使它变慢的修改是新的 OS (Ubuntu 17.04),可能带有这个新配置,因为旧的配置丢失了,因为我的 mac 死了。

data_directory = '/var/lib/postgresql/9.6/main'
hba_file = '/etc/postgresql/9.6/main/pg_hba.conf'
ident_file = '/etc/postgresql/9.6/main/pg_ident.conf'
external_pid_file = '/var/run/postgresql/9.6-main.pid'

listen_addresses = '*'
port = 5432
max_connections = 40

unix_socket_directories = '/var/run/postgresql'

shared_buffers = 4GB
temp_buffers = 2GB
work_mem = 512MB
maintenance_work_mem = 2GB
dynamic_shared_memory_type = posix

wal_level = minimal
fsync = off
synchronous_commit = off
full_page_writes = off
wal_buffers = 16MB

max_wal_size = 4GB
checkpoint_completion_target = 0.9

seq_page_cost = 1.0
random_page_cost = 1.5
effective_cache_size = 12GB

default_statistics_target = 500

logging_collector = on
log_directory = 'pg_log'
log_filename = 'query.log'
log_min_duration_statement = 0

debug_print_parse = off
debug_print_rewritten = off
debug_print_plan = off
debug_pretty_print = on
log_checkpoints = off
log_connections = off
log_disconnections = off

session_preload_libraries = 'auto_explain'
auto_explain.log_min_duration = '2s'

auto_explain.log_nested_statements = true
auto_explain.log_verbose = true

autovacuum = on
autovacuum_max_workers = 1

datestyle = 'iso, mdy'
timezone = 'UTC'


lc_messages = 'C'
lc_monetary = 'C'
lc_numeric = 'C'
lc_time = 'C'

default_text_search_config = 'pg_catalog.english'

max_locks_per_transaction = 2048

shared_preload_libraries = 'cstore_fdw'

根据请求,这是我拥有的另一个配置的旧备份,其中我手动调整了 1 项 (shared_buffers),其余几乎都是默认值。

更新 跳过旧配置 我用旧配置替换了配置,仍然遇到同样的问题,只是现在一切都变慢了。

否table更新 当我添加

时,查询再次变得快如闪电
ANALYZE source_table1;
ANALYZE source_table2;
ANALYZE source_table3;

在查询的最大 table 上,在 运行 查询之前。我以前不必这样做,而且效果很好。

这是一个可以解释您所看到的行为的场景。这假设 source_table{1,2,3} 在计算查询之前直接重建(当它是 ETL 的一部分时会发生):

之前:

  • 已为查询创建 table 源
  • autovacuum 有时间对 table 进行分析,而其他一些进程已完成
  • postgres 在查询中选择正确的计划

如果现在数据或 ETL 发生了一点变化,这导致 postgres 在查询之前没有时间进行 autovacuum,那么统计信息将关闭并且查询执行时间会激增。