2015-12-25 2 views
6

Я использую Postgresql 9.4 для базы данных модели. Моя таблица выглядит примерно так:Настройка производительности Postgresql и использования памяти в рабочем процессе python

CREATE TABLE table1 (
sid INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('table1_sid_seq'::regclass), 
col1 INT, 
col2 INT, 
col3 JSONB); 

Мой Python 2.7 рабочий процесс часто выглядит следующим образом:

curs.execute("SELECT sid, col1, col2 FROM table1") 
data = curs.fetchall() 
putback = [] 
for i in data: 
    result = do_something(i[1], i[2]) 
    putback.append((sid, result)) 
del data 
curs.execute("UPDATE table1 
       SET col3 = p.result 
       FROM unnest(%s) p(sid INT, result JSONB) 
       WHERE sid = p.sid", (putback,)) 

Это, как правило, работает достаточно хорошо и эффективно. Однако для больших запросов использование памяти Postgresql иногда проходит через крышу (> 50 ГБ) во время команды UPDATE, и я считаю, что ее убивает OS X, потому что я получаю WARNING: terminating connection because of crash of another server process. Мой MacBook Pro имеет 16 ГБ оперативной памяти, и в запросе есть 11M строк, каждый из которых содержит около 100 символов данных для записи.

Мои postgresql.conf:

default_statistics_target = 50 
maintenance_work_mem = 512MB 
constraint_exclusion = on 
checkpoint_completion_target = 0.9 
effective_cache_size = 4GB 
work_mem = 256MB 
wal_buffers = 16MB 
checkpoint_segments = 128 
shared_buffers = 1024MB 
max_connections = 80 

Так интересно

  1. Почему мой запрос потребляя иногда чрезмерное количество оперативной памяти?
  2. Как я могу контролировать использование памяти и все еще гарантировать хорошую производительность?
  3. Есть ли хорошее руководство или инструмент для настройки Postgresql?

Update:
Я уверен, что @wildplasser точно определили мою проблему. В комментариях он предлагает сначала сбросить данные в базу данных и распаковать их оттуда. К сожалению, я не мог понять, как реализовать его предложение. Если у кого-то есть идея, как это сделать, их ответ будет с радостью принят.

+0

1) ваш work_mem (скорее) высокий, и вы (вероятно) не имеют структуры таблицы. 2) спроектируйте свою базу данных. 3) см. 2 BTW: ваш выбор выбирает * все * строки (и я не понимаю ваш запрос на обновление.) – wildplasser

+0

Да. Ваш стол может выглядеть как электронная таблица, я не знаю. Да. – wildplasser

+0

BTW: Я не понимаю слова о вас, но это выглядит так, как будто вы втягиваете всю таблицу db в набор или массив python и используете это (в разобранном виде) для обновления той же таблицы. – wildplasser

ответ

1

Мой обходной путь является ломтик putback с простой функцией, как предложено here:

def chunk(l, n): 
    n = max(1, n) 
    return [l[i:i + n] for i in range(0, len(l), n)] 

, а затем

for chunk in chunk(putback, 250000): 
    curs.execute("UPDATE table1 
        SET col3 = p.result 
        FROM unnest(%s) p(sid INT, result JSONB) 
        WHERE sid = p.sid", (chunk,)) 

Это работает, т.е. сохраняет объем памяти в узде, но не очень элегантный и медленнее, чем сброс всех данных сразу, как я обычно делаю.

Смежные вопросы