2017-05-24 37 views
0

我正在運行一系列非常長的語句,移動大量數據。有關聲明看起來像是沿着這條線:聲明比平常慢250倍

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

這會創建表並使用大約60000個大行填充它。通常需要大約1秒來執行此聲明。 「通常」意味着完全相同的環境(所有表和數據都是由腳本創建的 - 無需人工交互,因此相同環境的所有實例在涉及數據和數據結構時是相同的),但是在不同的機器上,只需要1秒來執行此操作。

但是在我擁有的新機器上,這條語句突然需要4.5分鐘才能完成。在此期間,Postgresql佔用了100%的CPU內核。在那段時間裏,如果我打開一個新的連接,比如說用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活性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' 

每請求,這是一箇舊的備份,我有另一種配置,在這裏我手動調整僅1項數(shared_buffers)的,剩下的就是幾乎默認。

更新 跳過舊的配置 我更換了配置與舊的,仍然得到了同樣的問題,但現在一切都慢。

可觀的更新 查詢變得快如閃電當我再次對所查詢,運行查詢之前最大的表中添加

ANALYZE source_table1; 
ANALYZE source_table2; 
ANALYZE source_table3; 

。我以前不必這樣做,它的工作非常好。

+0

正如我之前解釋過的,「慢」是相對於完全相同的查詢,在相同的EXACT數據庫上執行的,甚至在相同的機器上執行,只是使用不同的客戶端。所有機器,所有情況下,當這個查詢執行時,它不到一秒鐘。唯一不同的是,它在一個新系統上以psql自動化腳本的順序運行。 – AlexanderMP

+0

如何執行「慢」查詢?使用不同的客戶端沒有任何意義。 –

+0

「慢」查詢由PHP腳本執行,通過shell命令'psql',沿着無數更大,更小的查詢執行,不受此影響。 – AlexanderMP

回答

1

這是一個可以解釋您所看到的行爲的場景。這假定source_table {1,2,3}的直重建計算查詢之前(當它是ETL的一部分會發生):

之前:

  • 爲源表查詢創建
  • 自動清理有時間做餐桌上的ANALYZE而其他一些過程完成
  • 的Postgres選擇正確的計劃上查詢

如果現在數據或ETL瓚ges一點,這導致postgres在查詢之前沒有時間進行自動清理,然後統計信息關閉,查詢執行時間爆炸。