Журнал коннектов к БД - средн. и макс. количество одновременных коннектов.

skorohod
Дата: 04.10.2005 15:51:11
FB 1.5.2
В БД есть таблица - журнал коннектов пользователей со след. структурой:
CREATE TABLE USER_LIST_ARCHIV (
USER_LIST_CURRENT_ID INT_ID NOT NULL /* INT_ID = INTEGER NOT NULL */,
LOGIN LOGIN_NAME NOT NULL /* LOGIN_NAME = VARCHAR(64) */,
CONNECT_NUMBER INT_ID NOT NULL /* INT_ID = INTEGER NOT NULL */,
PC_NAME STRING_64 NOT NULL COLLATE PXW_CYRL /* STRING_64 = VARCHAR(64) */,
APPLICATION_NAME STRING_32 NOT NULL COLLATE PXW_CYRL /* STRING_32 = VARCHAR(32) */,
DATE_CONNECT DATE_TIME_NOT_NULL_VALUE NOT NULL /* DATE_TIME_NOT_NULL_VALUE = TIMESTAMP DEFAULT current_timestamp NOT NULL */,
DATE_END DATE_TIME_VALUE /* DATE_TIME_VALUE = TIMESTAMP */,
FIRM_IDENT INT_TERRITORY NOT NULL /* INT_TERRITORY = INTEGER NOT NULL */
);
Т.е. БД используется разными приложениями одновременно кучей юзеров.
В таблице больше 100000 записей.
Нужно по этой табличке посчитать среднее и максимальное(пиковое) значение одновременно подключенных юзеров за все время "наблюдений". Не спрашивайте кому и зачем - ну вот надо!
Есть мысль связать таблицу саму на себя по условиям A.DATE_CONNECT >= B.DATE_CONNECT и A.DATE_CONNECT <= B.DATE_END (т.е. по каждой временной точке A.DATE_CONNECT проверяем всех, кто уже вошел но еще не вышел), результат сгруппировать по A.DATE_CONNECT и посчитать среднее и максимальное.
Только простое связывание - и select...select и select...join по таким условиям дает громадный результат, знач. нужно добавить первым ограничение join-а по Дата(A.DATE_CONNECT)=Дата(B.DATE_CONNECT) только вот как это сделать?! Как вытащить из поля TIMESTAMP значение DATE и сравнить его с таким же значением без учета временной составляющей?
Если есть альтернативные предложения - как ограничить join - буду признателен.
Если есть альтернативные предложения - как посчитать макс. и средн. - буду признателен вдвойне.
fraks
Дата: 04.10.2005 16:32:46
Я бы дума в след. сторону:

Сначала из лога надо получить последовательность событий коннекта и дисконнектав хронологическом порядке, типа так:

select DATE_CONNECT, 1
from log
UNION ALL
select DATE_END, -1
from log
order by 1

Этот запрос засунул бы в процедуру, и там бы подсчитывал текущее значение кол-ва коннектов.

create procedure test
returns(data timestamp, cnt integer)
as 
declare variable v: integer;
begin
  cnt = 0;
  for select DATE_CONNECT, 1
       from log
       UNION ALL
       select DATE_END, -1
       from log
       order by 1
       into :data, :v do begin
         cnt = cnt + :v:
         suspend;
       end
end

Ну и по результату этой процедуры уже можно делать запросы по поводу max, min и прочего...

Писал прямо из мозга (с) просьба не стрелять по синтаксису.
sag494
Дата: 04.10.2005 16:38:11
Привет,
skorohod
Не спрашивайте кому и зачем - ну вот надо!
...
Если есть альтернативные предложения - как посчитать макс. и средн. - буду признателен вдвойне.
предложу лобовое решение, которое особо подходит для гоняния на копии рабочей базы (дабы своей монстровостью не уложить рабочий сервер).
имхо, имеет смысл анализировать только временные метки соответсвующие DATE_CONNECT и DATE_END.
Сделать хп такого вида:
create procedure xp
returns (
    P_DATA timestamp,
    P_COUNT integer)
as begin  
    for select distinct DATE_CONNECT
    from USER_LIST_ARCHIV 
    union
    select distinct DATE_END
    from USER_LIST_ARCHIV 
    INTO :P_DATA
  do
  begin
    i=0;
    select count(*)
    from USER_LIST_ARCHIV 
    where :P_DATA between DATE_CONNECT and DATE_END
    into :P_COUNT;
    suspend;
  end
end

и уже по селекту по этой хп вычислять max и avg.
Хорошо бы чтобы для between использовался индекс и внешний цикл for_select все же был бы ограничен какими-то рамками.
Юрий Носов
Дата: 04.10.2005 16:58:04
IMHO тут две совсем разные задачи.
А. Максимальное число одновременных коннектов.
1. Упорядочить по возрастанию моменты подключения и отключения.
2. Пройтись по этой таблице, каждое подключение считать с плюсом, отключение- с минусом. Максимальное значение и даст искомое.
Б. Среднее число коннектов.
1. Просуммировать время всех коннектов и поделить на общее время работы.
sag494
Дата: 04.10.2005 16:59:49
fraks
select DATE_CONNECT, 1
from log
UNION ALL
select DATE_END, -1
from log
order by 1
Этот запрос засунул бы в процедуру, и там бы подсчитывал текущее значение кол-ва коннектов.
Красиво!
kdv
Дата: 04.10.2005 17:31:11
не совсем по вопросу, но все же. Вот типичный пример, почему я не люблю домены, и почему люди иногда перебарщивают с доменами:

DATE_CONNECT DATE_TIME_NOT_NULL_VALUE NOT NULL
/* DATE_TIME_NOT_NULL_VALUE = TIMESTAMP DEFAULT current_timestamp NOT NULL */

это ж вообще удолбаться можно. Домен невообразимого имени, с not null, да еще и столбцу not null сказан!
И все это вместо того чтобы написать

DATE_CONNECT TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL.

Причем, думаю, not null тут можно выкинуть.
skorohod
Дата: 04.10.2005 17:53:30
Спасибо ответившим за хелп.
Действительно красиво если применять в лоб "+1 и -1", только в этом случае реалии жизни демонстрируют наличие отрицательного количества коннектов :)

DateTime__Flag_Conn
23.04.2004 17:53 1 0
23.04.2004 17:54 -1 0
23.04.2004 18:12 1 0
23.04.2004 18:12 -1 0
23.04.2004 18:13 1 0
23.04.2004 18:14 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 00:00 -1 0
26.04.2004 09:27 1 0
26.04.2004 09:27 -1 0
26.04.2004 09:43 1 0
26.04.2004 09:44 -1 0
26.04.2004 09:45 1 0
26.04.2004 09:46 -1 0

Думаю без ограничения подсчета внутри каждой даты (начиная каждый день с 0 коннектов с 9.00) тут не обойтись!
skorohod
Дата: 04.10.2005 18:00:09
2 kdv
Сорри, база не моя - просто пришлось разбираться.
Скрипт по таблице сделал IBExpert а саму таблицу - авторы когда-то.
Второй нот нулл дал "крестик" в поле "не пусто" интерфейса IBE.
Конечно это дублирование информации в скрипте, но приводит ли это к двойной проверке каждой записи - я пока не в курсе - с FB только начинаю...
kdv
Дата: 04.10.2005 18:38:06
к двойной проверке ничего не приводит. просто у столбца есть характеристики, которые могут перекрывать характеристики домена. например у домена not null нет, а у столбца, базирующемся на этом домене not null можно включить. Похоже в БД not null забабахано в обоих местах.
fraks
Дата: 05.10.2005 05:44:17
skorohod
Спасибо ответившим за хелп.
Действительно красиво если применять в лоб "+1 и -1", только в этом случае реалии жизни демонстрируют наличие отрицательного количества коннектов :)
Думаю без ограничения подсчета внутри каждой даты (начиная каждый день с 0 коннектов с 9.00) тут не обойтись!


Сначала я бы отрезал все записи у которых
((date_start is  NULL) or (date_end is NULL)) 
and (date_end < date_start)