2014-11-12 3 views
0

У меня проблема с производительностью, когда я пытаюсь создать временную таблицу. Следующий код является частью функции plpgsql:Вставка строки в таблицу temp

StartTime := clock_timestamp(); 
CREATE TEMP TABLE wo_tmp WITH (OIDS) AS 
SELECT workorders1_.woid AS w_id, workorders1_.woid4seg AS w_id4seg 
FROM common.workorders workorders1_ 
INNER JOIN common.lines lines2_ ON workorders1_.wolineid=lines2_.lineid 
INNER JOIN common.products products2_ ON workorders1_.woprodid=products2_.prodid 
INNER JOIN common.depts depts3_ ON lines2_.linedeptid=depts3_.deptid 
WHERE workorders1_.wostatus='F' 
    AND workorders1_.wotypestatus = ANY ('{R,C,I,D}'::text[]) 
AND (p_deptid = 0 OR (depts3_.deptid = p_deptid AND ((p_deptid = 5 AND workorders1_.wosegid = 1) OR workorders1_.wosegid = 4))) 
AND (p_lineid = 0 OR lines2_.lineid = p_lineid) 
AND (p_prodid = 0 OR products2_.prodid = p_prodid) 
    AND (p_nrkokili = 0 OR workorders1_.wonrkokili = p_nrkokili) 
    AND (p_accepted = TRUE OR workorders1_.worjacceptstatus = 'Y') 
    AND workorders1_.wodateleaverr BETWEEN p_dfr AND p_dto 
    AND lines2_.status <> 'D'; 

CREATE INDEX wo_tmp_w_id_idx 
    ON wo_tmp USING btree (w_id ASC NULLS LAST); 
CREATE INDEX wo_tmp_w_id4seg_idx 
    ON wo_tmp USING btree (w_id4seg ASC NULLS LAST); 

    EndTime := clock_timestamp(); 
    Delta := extract('epoch' from EndTime)::bigint - extract('epoch' from StartTime)::bigint; 
    RAISE NOTICE 'Duration [0] in seconds=%', Delta; 

Вот explain analyze отчета: http://explain.depesz.com/s/uerF
Это странно, потому что, когда я исполняю эту функцию, я получаю уведомление: Duration [0] in seconds=11. Я проверяю запрос, не создавая временную таблицу, и время результата равно ~300ms.

Возможно ли, что вставка записей (~ 73k) во временную таблицу занимает 11 секунд? Могу ли я ускорить его?

+0

Создание индекса может занять некоторое время. Запустите 'EXPLAIN ANALYZE' для каждого запроса внутри процедуры. –

+0

Я побежал, но только создание временной таблицы занимает некоторое время. – bemol

+0

Пожалуйста, всегда * включайте заголовок и нижний колонтитул функции, которые являются важными деталями. Кроме того, [pg 8.4 достигло eol и больше не поддерживается] (http://www.postgresql.org/support/versioning/). Срочно рассмотрите возможность обновления до текущей версии. –

ответ

2

При заливке временной таблицы внутри функций, вы можете найти больше чем один вопрос:

  • запирающих вопросы - каждая таблица температуры является таблицу с некоторыми полями в системном каталоге. Интенсивное создание и удаление этих таблиц создает большие накладные расходы с блокировкой лотов. Иногда временные таблицы могут быть заменены массивами. Это не ваше дело, потому что вам нужны индексы.

  • слепое оптимизация - встроенный SQL в функциях PlpgSQL оптимизирован для большинства распространенных значений (этот механизм несколько улучшился в PostgreSQL 9.2 (но все еще с возможными проблемами производительности). Он не оптимизирован для текущих значений - и этот факт может обеспечить . некоторые проблемы с производительностью Тогда динамический SQL необходимо Некоторые звенья этой проблемы (one и second)

  • некоторых шоссе или файловой системой вопросов, -.. меня немного запутался о помощи WITHOUT OIDS это выглядит как файловая система ужасно узкое место для вас. Таблицы Temp хранятся в кеше файловой системы - хранение 53K строк должно быть быстрым .. удаление четырех байтов (с 35) не слишком большое изменение.

    postgres=# create table t1 with (oids) as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 302.083 ms 
    postgres=# create table t2 as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 267.459 ms 
    postgres=# create temp table t3 with (oids) as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 154.431 ms 
    postgres=# create temp table t4 as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 153.085 ms 
    postgres=# \dt+ t* 
            List of relations 
        Schema | Name | Type | Owner | Size | Description 
    -----------+------+-------+-------+---------+------------- 
    pg_temp_2 | t3 | table | pavel | 3720 kB | 
    pg_temp_2 | t4 | table | pavel | 3160 kB | 
    public | t1 | table | pavel | 3720 kB | 
    public | t2 | table | pavel | 3160 kB | 
    (4 rows) 
    

Запись 3MB файла в файловой системе должен быть значительно меньше, чем 1сек .. так странно для 11 сек накладных расходов. постскриптум по умолчанию temp_buffers - 8 МБ, поэтому ваш результат должен храниться только в памяти - и, вероятно, эта гипотеза ложна - и, более вероятно, является гипотезой слепой оптимизации.

+0

Спасибо, очень хорошее объяснение, я попытаюсь использовать ваши советы и дам вам знать. – bemol

+0

Еще одна вещь, мне не нужны индексы, я использовал ее для лучшей производительности следующих запросов, но я могу пожертвовать ~ 1 сек, если создание временной таблицы будет длиться 5 секунд. Sry для английского – bemol

+0

Изменение динамического запроса увеличило производительность, как я и хотел. Это отличная работа @Pavel Stehule, спасибо вам большое. Ты мой герой. :) – bemol

1

Для начала, не используйте WITH (OIDS) для временных таблиц. Когда-либо. Использование OID в обычных таблицах не рекомендуется. Это вдвойне подходит для временных таблиц. Также уменьшает требуемое RAM/пространство на диске, что, вероятно, является основной шейкой бутылки. Переключить на: WITHOUT OIDS.

Далее, вероятная причина (образованная догадка) - это отсутствие буферов temp, которые заставляют таблицу temp разливаться на диск. Проверьте фактический размер временной таблицы с

SELECT pg_size_pretty(pg_relation_size('wo_tmp')); 

И установить temp_buffers соответственно, возможно, для сессии только - округлить великодушно, достаточно, чтобы избежать записи на диск.

Деталь:

+0

Благодарим вас, 'БЕЗ ОЙДДА 'ускорьте это. – bemol

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