Я пытаюсь найти запрос, который находит истинное число максимальных одновременных пользователей в интервале на основе исторической записи пользовательских логинов (в данном случае интервал является ежедневным).
Приведенный ниже запрос будетвыполните эту работу, за исключением того, что для таблицы размером 500 тыс. записей выполнение запроса займет более 8 часов и в конечном итоге будет завершено до завершения.
SELECT DATE(DBINFO('utc_to_datetime', login_utc)) AS utcDate,
MAX(NVL(cumeins, 0) - NVL(cumeouts, 0)) AS Concurrent
FROM (
SELECT s.login_utc,
(SELECT count(*)
FROM root.haglog s2
WHERE s2.login_utc <= s.login_utc
) AS cumeins,
(SELECT count(*)
FROM root.haglog s2
WHERE s2.logout_utc <= s.login_utc
) AS cumeouts
FROM root.haglog s GROUP BY login_utc
) s
GROUP BY 1
ORDER BY 1 ASC;
Таким образом, поля login_utc / logout_utc не индексируются,но есть доступное индексированное поле с именем row_date (просто дата записи без компонента time).Я подумал, чтобы попытаться использовать этот индекс для ускорения процесса выбора, как показано ниже, так что мы сравниваем только с неиндексированными полями в том случае, если рассматриваемая строка уже совпадает с датой (намного меньшим подмножеством):
SELECT DATE(DBINFO('utc_to_datetime', login_utc)) AS utcDate,
MAX(NVL(cumeins, 0) - NVL(cumeouts, 0)) AS Concurrent
FROM (
SELECT s.login_utc,
(SELECT count(*)
FROM root.haglog s2
WHERE CASE
WHEN DATE(DBINFO('utc_to_datetime', s2.login_utc)) = s.row_date
THEN s2.login_utc <= s.login_utc
ELSE 0
END
) AS cumeins,
(SELECT count(*)
FROM root.haglog s2
WHERE CASE
WHEN DATE(DBINFO('utc_to_datetime', NVL(s2.logout_utc,0))) = s.row_date
THEN s2.logout_utc <= s.login_utc
ELSE 0
END
) AS cumeouts
FROM root.haglog s GROUP BY login_utc, row_date
) s
GROUP BY 1
ORDER BY 1 ASC;
Но оператор case, структурированный выше, приводит к синтаксической ошибке, вероятно потому, что он не может напрямую передать логику условного оператора.Я пытаюсь использовать здесь оператор case, потому что не гарантируется короткое традиционное вычисление схемы (в противном случае я бы просто сделал 'DATE (DBINFO (' utc_to_datetime ', s2.login_utc)) = s.row_date AND s2.login_utc <= s.login_utc'). </p>
Есть ли лучший способ уменьшить вычислительную сложность исходного запроса, и если нет, то как я могу структурировать запрос для использования индекса row_date?
UPDATE
Я опробовал предложение О. Джоунса и получил следующий запрос:
SELECT MAX(concurrency) concurrency, row_date FROM (
SELECT s.row_date, t.t, COUNT(*) concurrency
FROM root.haglog s
JOIN (
SELECT DISTINCT login_utc t FROM root.haglog s
UNION
SELECT DISTINCT (NVL(logout_utc, 0) + 1) t FROM root.haglog s
) t ON s.login_utc >= t.t AND s.logout_utc < t.t
GROUP BY s.row_date, t.t
) a GROUP BY row_date ORDER BY row_date ASC
Этот запрос был выполнен быстро, но он вернул только 7 результатов (набор данных - 500 КБ):
concurrency row_date
----------- ----------
1 2018-05-04
1 2018-06-05
1 2018-06-26
1 2018-07-10
1 2018-08-10
1 2018-09-10
1 2018-09-19
Вот некоторые примеры данных (нет, на самом деле пользователь, вошедший в систему с мая), отсутствует:
row_date seq_num logid login_utc logout_utc logout_date
---------- ---------- ------- ---------- ---------- -----------
2018-05-02 1525229404 1201111 1525247404 1525253897 2018-05-02
2018-05-02 1525229463 1201112 1525247463 1525255395 2018-05-02
2018-05-02 1525230080 1011111 1525248080 1525266019 2018-05-02
2018-05-02 1525231420 1211111 1525249420 NULL NULL
Схема будет описана здесь: https://downloads.avaya.com/elmodocs2/contact_center/r3v11/780701_1/780701_1.pdf
ОБНОВЛЕНИЕ 2
Как для моего исходного запроса, так и для предложенного в ответе О. Джонсом, я вывел соответствующие столбцы во временную таблицу, сделал индексы для всех отношенийи до сих пор не идти.Запрос выполняется в течение пары часов, а затем уничтожается на сервере (клиент все еще считает, что он выполняется).На этом этапе, если бы я мог изменить свойство времени выполнения сервера, чтобы он мог просто работать до его завершения, это было бы хорошо ....