Оптимизация запросов Postgresql - PullRequest
2 голосов
/ 20 марта 2012

У меня есть две таблицы, и я должен запросить мою базу данных postgresql.В таблице 1 содержится около 140 миллионов записей, а в таблице 2 - около 50 миллионов записей из следующих.

таблица 1 имеет следующую структуру:

tr_id bigint NOT NULL, # this is the primary key
query_id numeric(20,0),       # indexed column
descrip_id numeric(20,0)      # indexed column

, а таблица 2 имеет следующую структуру

query_pk  bigint # this is the primary key
query_id  numeric(20,0)    # indexed column
query_token numeric(20,0)

Пример БД таблицы1 будет

1 25 96
2 28 97
3 27 98
4 26 99

Пример БД таблицы 2 будет

 1 25 9554
 2 25 9456
 3 25 9785
 4 25 9514
 5 26 7412
 6 26 7433
 7 27 545
 8 27 5789
 9 27 1566
10 28 122
11 28 1456

Я предпочитаю запросы, в которых я мог бы делать запросы в блоках tr_id.В диапазоне 10 000, поскольку это мое требование.

Я хотел бы получить вывод следующим образом

25  {9554,9456,9785,9514}
26  {7412,7433}
27  {545,5789,1566}
28  {122,1456}

Я пытался следующим образом

select query_id, 
       array_agg(query_token) 
from sch.table2 
where query_id in (select query_id 
                   from sch.table1 
                   where tr_id between 90001 and 100000) 
group by query_id 

Я выполняю следующий запрос, который занимает около 121346 мс, и когда запускается около 4 таких запросов, это все равно занимает больше времени.Можете ли вы помочь мне оптимизировать то же самое.

У меня есть машина, которая работает на Windows 7 с i7 2nd gen proc с 8 ГБ ОЗУ.

Ниже приведена моя конфигурация postgresql

shared_buffers = 1GB    
effective_cache_size = 5000MB
work_mem = 2000MB

Что я должен сделать, чтобы оптимизировать его.

Спасибо

РЕДАКТИРОВАТЬ: было бы здорово, если бы результаты упорядочены в следующем формате

25  {9554,9456,9785,9514}
28  {122,1456}
27  {545,5789,1566}
26  {7412,7433}

то есть в соответствии с порядком запроса в таблице1, упорядоченным по tr_id.Если это вычислительно дорого, может быть в клиентском коде, я бы попытался оптимизировать его.Но я не уверен, насколько эффективно это будет.

Спасибо

1 Ответ

2 голосов
/ 20 марта 2012

Запрос

Я ожидаю, что JOIN будет намного быстрее, чем IN условие, которое вы имеете в настоящее время:

SELECT t2.query_id
      ,array_agg(t2.query_token) AS tokens
FROM   t1
JOIN   t2 USING (query_id)
WHERE  t1.tr_id BETWEEN 1 AND 10000
GROUP  BY t1.tr_id, t2.query_id
ORDER  BY t1.tr_id;

Это также сортирует результаты по запросу. query_token остается несортированным за query_id.

Индексы

Очевидно, вам нужны индексы для t1.tr_id и t2.query_id.
У вас, очевидно, уже есть тот:

CREATE INDEX t2_query_id_idx ON t2 (query_id);

Многоколонный индекс на t1 может повысить производительность (вам придется проверить):

CREATE INDEX t1_tr_id_query_id_idx ON t1 (tr_id, query_id);

Конфигурация сервера

Если это выделенный сервер базы данных, вы можете увеличить значение для effective_cache_size еще немного.

@ Фрэнк уже дал совет по work_mem. Цитирую руководство :

Обратите внимание, что для сложного запроса несколько операций сортировки или хеширования могут работать параллельно; каждая операция будет разрешено использовать как можно больше память, поскольку это значение указывает, прежде чем он начинает записывать данные в временные файлы. Кроме того, несколько сеансов могут операции одновременно. Следовательно, общая используемая память может быть много раз значение work_mem;

Он должен быть достаточно большим, чтобы можно было сортировать ваши запросы в оперативной памяти. 10 МБ - это более чем достаточно, чтобы вместить 10000 ваших строк одновременно. Установите его выше, если у вас есть запросы, которые нуждаются в большем количестве за один раз.

При выделении 8 ГБ на выделенном сервере базы данных у меня будет соблазн установить shared_buffers как минимум на 2 ГБ.

shared_buffers = 2GB    
effective_cache_size = 7000MB
work_mem = 10MB

Дополнительные советы по настройке производительности в Postgres Wiki .

...