PostgreSQL - Почему некоторые запросы к большим наборам данных так невероятно медленны - PullRequest
1 голос
/ 19 мая 2010

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

Первый тип - это последовательное сканирование, обновляющее все записи:

Update rcra_sites Set street = regexp_replace(street,'/','','i')

rcra_sites имеет 700 000 записей. Это займет 22 минуты от pgAdmin! Я написал функцию vb.net, которая просматривает каждую запись и отправляет запрос на обновление для каждой записи (да, 700 000 запросов на обновление!), И он выполняется менее чем в два раза. Хммм ....

Второй тип - это простое обновление с отношением и последующим сканированием:

Update rcra_sites as sites 
Set violations='No' 
From narcra_monitoring as v 
Where sites.agencyid=v.agencyid and v.found_violation_flag='N'

narcra_monitoring имеет 1 700 000 записей. Это займет 8 минут. Планировщик запросов отказывается использовать мои индексы. Запрос выполняется намного быстрее, если я начну с set enable_seqscan = false; . Я бы предпочел, чтобы планировщик запросов выполнял свою работу.

У меня есть соответствующие индексы, я пылесосил и анализировал. Я оптимизировал свои shared_buffers и ffective_cache_size , лучше всего я знаю, чтобы использовать больше памяти, поскольку у меня есть 4 ГБ. Мое оборудование чертовски хорошо. Я использую v8.4 в Windows 7.

Является ли PostgreSQL медленным? Или я все еще что-то упускаю?

Ответы [ 2 ]

1 голос
/ 19 мая 2010

Возможно, попробуйте уменьшить ваш random_page_cost (по умолчанию: 4) по сравнению с seq_page_cost: это уменьшит предпочтение планировщика для сканирования seq, сделав случайный доступ, управляемый индексами, более привлекательным.

Еще одна вещь, которую нужно иметь в виду, это то, что MVCC означает, что обновление строки довольно дорого. В частности, обновление каждой строки в таблице требует удвоения объема памяти для таблицы, пока она не будет очищена. Таким образом, в вашем первом запросе вы можете захотеть квалифицировать свое обновление:

UPDATE rcra_sites Set street = regexp_replace(street,'/','','i')
                  where street ~ '/'

(afaik postgresql не подавляет обновление автоматически, если похоже, что вы на самом деле ничего не обновляете. В 8.4 (?) Добавлена ​​стандартная триггерная функция, позволяющая вам это сделать, но, возможно, лучше обратитесь к клиенту)

0 голосов
/ 20 мая 2010

При обновлении строки записывается новая версия строки.

Если новая строка не помещается в один и тот же блок диска, то каждая запись индекса , указывающая на старую строку, должна быть обновлена, чтобы указывать на новую строку.

Не только индексы обновленных данных требуют обновления.

Если у вас rcra_sites много индексов и только одно или два часто обновляемых поля, вы можете получить выгоду, разделив часто обновляемые поля в свою собственную таблицу.

Вы также можете уменьшить процент fillfactor ниже значения по умолчанию, равного 100, чтобы некоторые обновления могли приводить к записи новых строк в один и тот же блок, в результате чего индексы указывали на этот блок. не нуждается в обновлении.

...