语句比平时慢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,那么统计信息将关闭并且查询执行时间会激增。
我正在 运行宁一系列很长的陈述,移动大量数据。有问题的陈述看起来像这样:
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.
所以这绝对不是脚本,而是关于 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,那么统计信息将关闭并且查询执行时间会激增。