我正在运行一系列非常长的语句,移动了大量数据。有问题的陈述看起来像是这样的:
CREATE TABLE a (...);
WITH cte_1 AS (...),
cte_2 AS (...)
INSERT INTO a (...)
SELECT ....
这将创建表并用大约60,000个大行填充它。通常需要大约1秒来执行此声明。 “通常”意味着完全相同的环境(所有表和数据都是由脚本创建的 - 没有手动交互,因此相同环境的所有实例在数据和数据结构方面都是相同的)但是在不同的机器上,只需要1秒执行此操作。
但是在我拥有的新机器上,此声明突然需要4.5分钟才能完成。在此期间,Postgresql占用CPU核心的100%。在此期间,如果我使用DBeaver打开一个新连接,并运行完全相同的查询,只需一次更改(创建表b
,然后从完全相同的数据源插入),在第一个查询运行期间,它需要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
在数百种语句中,在各种模式中,具有各种复杂性,这是唯一受影响的语句。唯一被修改使它变慢的是新操作系统(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'
根据请求,这是我的另一个配置的旧备份,我手动调整了一个项目(shared_buffers),其余的几乎默认。
更新 跳过旧配置 我用旧的替换了配置,但仍然遇到了同样的问题,除了现在一切都慢了。
值得注意的更新 当我添加
时,查询再次变得闪电般快速ANALYZE source_table1;
ANALYZE source_table2;
ANALYZE source_table3;
在运行查询之前查询的最大表。我以前没必要这样做,而且工作得非常好。
答案 0 :(得分:1)
这是一个可以解释您所看到的行为的场景。这假设source_table {1,2,3}在计算查询之前是直接重建的(因为当它是ETL的一部分时会发生):
在:
如果现在数据或ETL发生了一些变化,这导致postgres在查询之前没有时间进行autovacuum,那么统计信息就会关闭,查询执行时间也会爆炸。