2015-11-27 12 views
1

У меня проблема с производительностью при объединении двух столбцов в один для таблицы размером 7 м записей.Объединить два столбца в один

Моя главная цель:

  • слияние open_time и close_time в одном «время» колонка
  • время заказа и account_ID по DESC
  • проверка колонки op_type для каждого account_ID на основе упорядоченных записей по времени и account_id:
    • Если op_type был изменен с 0 на 1 или наоборот для первой и второй записей, сделайте счетчик +1.
    • Если параметр op_type был изменен с 0 на 1 или наоборот на второй и третий записи, снова сделайте счетчик +1.
    • и так далее для всех записей для каждого account_ID

account_id, open_time и close_time индексируются.

Вариант № 1: Объединить open_time и close_time столбцов в один столбец «времени», используя объединение двух отдельных утверждений: время

select account_id, op_type, open_time as time, instrument_id 
from tmp_operations 
UNION 
select account_id, op_type=0, close_time as time, instrument_id 
from tmp_operations 

Выполнение объединение двух оператора выбора составляет более 4 000 000 мс и Все еще работает.

Вариант № 2: Объединить open_time и close_time столбцов в один столбец «времени» с использованием unnest массива:

SELECT 
    account_id, 
    op_type, 
    unnest(ARRAY[open_time, close_time]) as time, 
    instrument_id 
FROM risklive.operations_mt4 op 

Время выполнения unnesting массива составляет около 315 000 мс, который является более лучше. Спасибо, Мессенджер Габриэля!

Некоторые образцы, что я хочу видеть в результате временные отметки сливающихся:

 open_time    close_time      time 
"2015-08-19 09:18:24" "2015-08-19 09:20:40"   "2015-08-19 09:18:24" 
"2015-08-19 09:11:54" "2015-08-19 09:17:16" --> "2015-08-19 09:20:40" 
"2015-08-19 09:17:46" "2015-08-19 09:18:22"   "2015-08-19 09:11:54" 
                 "2015-08-19 09:17:16" 
                 "2015-08-19 09:17:16" 
                 "2015-08-19 09:17:46" 
                 "2015-08-19 09:18:22" 

Как для столбца op_type изменяет счетчик для каждой записи в ACCOUNT_ID:

account_id op_type   time 
    63004;  1; "2015-08-19 09:18:24" 
    63004;  1; "2015-08-19 09:20:40" 
    63004;  1; "2015-08-19 09:11:54" 
    63004;  1; "2015-08-19 09:17:16" <-- op_type will be changed in next entry 
    63004;  0; "2015-08-19 09:17:46" <-- counter = 1 
    63004;  0; "2015-08-19 09:18:22" <-- op_type will be changed in next entry 
    63004;  1; "2015-08-19 09:09:31" <-- counter = 2 
    63004;  1; "2015-08-19 09:09:31" 
    63004;  1; "2015-08-19 09:31:09" 
    63004;  1; "2015-08-19 09:32:07" <-- op_type will be changed in next entry 
    63004;  0; "2015-08-19 09:32:09" <-- counter = 3 
    63004;  0; "2015-08-19 09:57:44" <-- op_type will be changed in next entry 
    63004;  1; "2015-08-19 09:20:43" <-- counter = 4 
    63004;  1; "2015-08-19 09:31:51" 
    63004;  1; "2015-08-19 09:20:59" 
    63004;  1; "2015-08-19 09:31:51" 

Над изменениями op_type счетчик я не Не знаю, как реализовать в этот момент.

Как я могу настроить все это?

+0

Мне непонятно, чего вы пытаетесь достичь. Результат будет иметь столбец _single_ с именем 'open_time', он не будет иметь столбец с именем' close_time', потому что имена столбцов второго запроса не имеют значения. Пожалуйста, ** отредактируйте ** свой вопрос и добавьте некоторые примеры данных и ожидаемый результат на основе этих данных. –

+1

_Не проверено, и я не знаю, будет ли это работать для вас просто try_ 'coalesce (nullif (0, op_type), 1)' вместо '(CASE WHEN op_type = 0 THEN 1 ELSE 0 END)' –

+0

@wingedpanther I сомневаюсь, что 'COALESCE' - его самая большая проблема с точки зрения производительности, но +1 для введения функции' nullif'. Это удобный маленький дьявол :) –

ответ

1

Поскольку вы немного изменили свой вопрос, но после моего ответа я полностью переписал свой пост.

Отказ от ответственности:

Вы должны выполнить opperation требует слияния, и вся таблица порядка (7М строк) это каждый раз, когда бутылка шея. Возможно, вы не найдете решения, которые удовлетворят вас без изменения вашей оценки полностью. Тем не менее позвольте мне попробовать.

Первая проблема:

Так что ваша первая проблема была «слить» два столбца в один для всей таблицы строк 7М.Вы попробуйте UNION, которому нужны два seq scan. Как я предложить, прежде чем решение может быть с помощью агрегации массива и unnest (wchich вы сделали):

SELECT 
    account_id, 
    op_type, 
    unnest(ARRAY[open_time, close_time]) as time, 
    instrument_id 
FROM risklive.operations_mt4 op 

Вторая проблема:

рассчитывает op_type изменения для account_id в то время как по заказу «объединить» столбец времени. Для удобства чтения я использую CTE, чтобы поставить «объединенную таблицу».

Мы должны использовать подзапрос. На одном уровне мы проверяем изменения op_type с правильным порядком (используя lag()WINDOW FUNCTION, который возвращает значение одной строки перед текущей строкой). На втором уровне мы суммируем количество изменений op_type.

WITH merged_table AS (
    SELECT 
     account_id, 
     op_type, 
     unnest(ARRAY[open_time, close_time]) as time, 
     instrument_id 
    FROM risklive.operations_mt4 op 
) 
SELECT 
    account_id, SUM(abs(x)) as counter 
FROM (
    SELECT 
     m.account_id, 
     (m.op_type - lag(m.op_type) 
       OVER (PARTITION BY m.account_id ORDER BY time) 
     ) as zero_if_no_op_type_change 
    FROM merged_table m 
) sub 
GROUP BY account_id 

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

+0

Спасибо, Габриэль, это помогает мне объединить временные метки вместе с временем выполнения = 315 000 мс! =) Это лучше, чем объединение. Последнее место, где я застрял, - это счетчик изменений op_type. Есть ли у вас идеи, как можно обойтись без дублирования еще одного столбца op_type с обратными переменными и последующим новым сдвигом столбца op_type для дальнейшего сравнения одного столбца op_Type с другим. – user1376885

+0

Вы действительно меняете свой вопрос. Если честно, то, что вы делали ранее, «CASE WHEN» и «op_type» не делали то, что вы ожидаете, что сделало мой ответ не совсем хорошим. Я пытаюсь переписать свой ответ, чтобы соответствовать вашим критериям. –

+0

Спасибо, Габриэль, некоторые советы от вашего ответа очень помогают мне улучшить производительность! – user1376885

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