Периодически процесс загрузки в Qlikview подвисает

Автор d.pimkin, 09 февраля 2015, 01:35:21

« назад - далее »

d.pimkin

Доброго времени суток!

Такая вот проблема: периодически процесс загрузки скрипта подвисает, просто всю ОЗУ забивает и дальше ничего не происходит. Проблема периодическая: один и тот же скрипт, на одной машине ведет себя по-разному, т.е. что в скрипте не меняй, все равно такая проблема.
В прошлый раз помогло создание нового qvw файла и там постепенно, шаг за шагом, добавлял скрипт загрузки (после каждого этапа загружал). Сейчас проблема возникла так: тот же проект (один qvw файл) на одной машине под другим пользователем завис.

Машина: 8 ЦП, 32 ОЗУ.
ОЗУ он забивает очень плавно до упора, после чего помогает лишь обрубание процесса.

Скрипт, не работающий на одной и той же машине под разными пользователями.

ODBC CONNECT TO Zabbix;

Host_Groups:
SELECT
hg.hostid,
g.`name` GroupName
FROM
zabbix.hosts_groups hg
INNER JOIN zabbix.groups g ON g.groupid = hg.groupid
WHERE
hg.groupid IN (24, 26, 28, 186, 58, 126, 98, 187)
OR hg.groupid BETWEEN 172 AND 184;

SQL SELECT *
FROM zabbix.`ATM_info`;

Tmp:
LOAD
itemid as EchoId,
time,
value
From Avalibility_table.qvd (qvd);

Schedule:
Inner Join SQL SELECT EchoId,
    `end_dw`,
    `end_time`,
    `start_dw`,
    `start_time`
FROM zabbix.`ATM_info`;

Avalibility:
LOAD
EchoId,
time,
value,
((Interval#(Time(time))>=Interval#(Time(start_time)))and(Interval#(Time(time))<=Time(end_time)))and(((WeekDay(Date(time,'DD.MM.YYYY'))+1)>=start_dw)and((WeekDay(Date(time,'DD.MM.YYYY'))+1)<=end_dw)) as work_time
Resident Tmp;

DROP Table Tmp;


Когда в скрипт (для одного пользователя, через которого все работало) добавил код ниже, опять та же ситуация возникла.

//-------------------------------
Tmp:
LOAD
itemid as DelayId,
time,
value
From Delay2.qvd (qvd);

Schedule:
Inner Join SQL SELECT EchoId,
    `end_dw`,
    `end_time`,
    `start_dw`,
    `start_time`
FROM zabbix.`ATM_info`;

Delay:
LOAD
DelayId,
time,
value,
((Interval#(Time(time))>=Interval#(Time(start_time)))and(Interval#(Time(time))<=Time(end_time)))and(((WeekDay(Date(time,'DD.MM.YYYY'))+1)>=start_dw)and((WeekDay(Date(time,'DD.MM.YYYY'))+1)<=end_dw)) as work_time
Resident Tmp;

DROP Table Tmp;

//--------------------------------------

Tmp:
LOAD
itemid as PacketId,
time,
value
From Packet_loss2.qvd (qvd);

Schedule:
Inner Join SQL SELECT EchoId,
    `end_dw`,
    `end_time`,
    `start_dw`,
    `start_time`
FROM zabbix.`ATM_info`;

Packet_loss:
LOAD
PacketId,
time,
value,
((Interval#(Time(time))>=Interval#(Time(start_time)))and(Interval#(Time(time))<=Time(end_time)))and(((WeekDay(Date(time,'DD.MM.YYYY'))+1)>=start_dw)and((WeekDay(Date(time,'DD.MM.YYYY'))+1)<=end_dw)) as work_time
Resident Tmp;

DROP Table Tmp;


По логу виснет на присоединении двух таблиц. В таблицах (в qvd) по 78-79 млн. записей. Но все же первая часть скрипта, когда работает, занимает не более 2 минут.

admin

#1
День добрый.
Попробуйте такой подход - после оператора inner join ..., т.е. когда связали две таблицы, выгрузите результат в qvd, удалите открытые таблицы и загрузите промежуточную таблицу вновь.
Т.е. перед формированием таблицы на основе уже загруженной таблицы (load ... resident..) вставить 
STORE Tmp into tmp.qvd (qvd);
DROP Table Tmp;

Затем загрузить требуемую таблицу не из памяти а  From tmp.qvd (qvd);
Для начала без формирования поля work_time а затем с вычислением интервала work_time и сравнить результаты загрузки.

Еще как вариант, сделайте отдельный обработчик источника данных, т.е. одним сценарием заберите все данные через odbc и сохраните в qvd.
В приложении пользователя уже не будет нужды обращаться к источнику, в вашем распоряжении будет только тот массив данных, который необходим.

d.pimkin

Спасибо за советы.

Первый способ не помог ни без формирования поля work_time, ни с ним.

Отличная мысль на счет создания готового qvd с уже посчитанным work_time, не знаю почему, но до этого почему-то не сообразил. Буду пробовать.

А у Вас никаких предположений нет, почему вообще так происходит?

admin

#3
Не видя данных сложно что-либо сказать определенно.

Host_Groups:
SELECT
hg.hostid,
g.`name` GroupName
FROM
zabbix.hosts_groups hg
INNER JOIN zabbix.groups g ON g.groupid = hg.groupid
WHERE
hg.groupid IN (24, 26, 28, 186, 58, 126, 98, 187)
OR hg.groupid BETWEEN 172 AND 184;

Почему не используете предварительный LOAD?
Что грузит в итоге? Проверяйте отдельно каждый запрос.
Старайтесь избегать в odbc запросах "WHERE hg.groupid IN (24, 26, 28, 186, 58, 126, 98, 187) OR hg.groupid BETWEEN 172 AND 184" Либо применяя эти конструкции убедитесь в их корректной работе.
Проверяйте данные на этапе отладки, выгружая их в отдельный qvd.
Загрузка всех полей по умолчанию тоже сомнительная затея:

SQL SELECT *
FROM zabbix.`ATM_info`;


Потом, "LOAD itemid as EchoId,"  и "Inner Join SQL SELECT EchoId,"
Есть уверенность что qlikview формирует таблицу с полем EchoId а не echoid ?
Может он поэтому и ведет себя непредсказуемо. что ему непонятно что соединять? Регистр полей имеет значение.

d.pimkin

Действительно помогла выгрузка таблиц с уже посчитанным полем work_time в отдельный qvd.
Кстати, есть верноятность, что проблема была с регистром, т.к. пару раз исправлял.

На счет данных: загрузка прямым запросом таблицы Host_Groups работала корректно, зависал именно на моменте объединения Tmp и Schedule. А так, две таблицы hosts_groups и ATM_info, всегда загружались корректно, они небольшие - чуть больше тысячи записей. А вот те, что я грузил из qvd были по 80млн записей.

А что вы имели в виду под этим?
ЦитироватьПочему не используете предварительный LOAD?

И как можно избежать:
ЦитироватьСтарайтесь избегать в odbc запросах "WHERE hg.groupid IN (24, 26, 28, 186, 58, 126, 98, 187) OR hg.groupid BETWEEN 172 AND 184"
Мысль только перевести этот запрос на вьюшку в БД.

admin

#5
Предварительный load, конструкция типа:
load text(a) as [Поле А];
select sql a ftom b;

Сложные конструкции в прямых запросах - риски возникновения ошибок.
Когда она возникнет - не сразу будет очевидна.
Отсюда и рекомендация снимать слепок с БД в qvd и дальше уже обрабатывать средствами Qlikview.
Но это лишь рекомендация. При формировании ХД на QVD ряд таблиц я также обрабатываю уже через ODBC-драйвер. Просто лишний раз проверяю результат.

admin

Цитата: d.pimkin от 09 февраля  2015, 10:58:50  
Кстати, есть вероятность, что проблема была с регистром, т.к. пару раз исправлял.
Именно так, ODBC SQL SELECT возвращает имена полей в нижнем регистре.

d.pimkin

#7
Проблема опять повторилась.

Написал отдельное от клиентского приложение для выгрузки и обновления данных в qvd.
Сначала сделал выгрузку трех типов данных поэтапно в одном приложении: на втором типе зависла загрузка. Потом разделил на 3 приложения: вообще ни одно не работает, т.е. все зависают на начальном этапе.
Зависание фиксирую как по графику утилизации процессора сервера БД, откуда выгрузка идет (по графику видно, что никакого вывода данных не происходит), так и по загрузке ОЗУ сервера, на котором работает QlickView (ОЗУ стоит на месте, т.е. данными не забивается).

Вот так выглядит самый первый этап выгрузки, на котором, собственно, все и виснит:

tmp:
LOAD itemid as EchoId,
    time as EchoTime,
    value as EchoValue;
SQL SELECT
itemid,
FROM_UNIXTIME(clock) time,
`value`
FROM
zabbix.history_uint
WHERE
itemid in (SELECT EchoId FROM ATM_info);

STORE tmp into EchoTemp.qvd (qvd);
DROP Table tmp;


Предполагаю, что виснит из-за этой строчки itemid in (SELECT EchoId FROM ATM_info); Но на небольших объемах данных она не мешает. Например, если прописать itemid in (SELECT EchoId FROM ATM_info WHERE EchoId=25489);

Вопрос, как ее обойти?
Единственное, что приходит в голову, разделить на два этапа, т.е. сначала выгрузить всю таблицу, а потом из нее вычленить нужные строки. Но в таком случае, вместо 100млн строк, он будет выгружать 1млрд строк. Я считаю, что это не очень продуктивно.

admin

А как ODBC-драйвер отрабатывает запрос?
SQL SELECT
itemid,
FROM_UNIXTIME(clock) time,
`value`
FROM
zabbix.history_uint
WHERE
itemid in (SELECT EchoId FROM ATM_info);

Можно проверить сторонними средствами, не через Qlikview ?

d.pimkin

#9
Вот это я не знаю. А есть примеры, чем можно проверить?

БД MySQL, если что...

admin

А что имеется из средств работы с БД?
Запрос нормально отрабатывает на самом сервере? За какое время?
ODBC будет работать не быстрее чем на сервере.
Необходимо подключиться к БД через ODBC-драйвер и проверить результат выполнения запроса.

Chernov

Цитата: admin от 16 февраля  2015, 09:15:41  
FROM
   zabbix.history_uint
WHERE
itemid in (SELECT EchoId FROM ATM_info)
А у вас поле EchoID - в БД индексируемое, что вы его так просто его в подзапросе используете ?
Сколько у вас строк в обеих таблицах ?
И вообще сделайте через темповую таблицу, примерно так:

ЦитироватьLOAD itemid as EchoId,
    time as EchoTime,
    value as EchoValue;

SQL

CREATE TEMPORARY TABLE temp_table
SELECT EchoId FROM ATM_info

SELECT
   itemid,
   FROM_UNIXTIME(clock) time,
   `value`
FROM
   zabbix.history_uint
WHERE
itemid in (SELECT EchoId FROM temp_table);




d.pimkin

На данный момент проблему решил организацией выгрузки в два этапа: сначала выгружаю в qvd всю таблицу zabbix.history_uint, потом уже из нее выдергиваю нужные. Процесс  длится почти час.
Но в будущем таблица будет расширена в несколько раз, и тогда уже, как мне кажется, будет значительно быстрее выдергивать только те строки которые мне нужны. Поэтому вопрос актуален.
Сейчас в таблице zabbix.history_uint порядком 250млн. строк, но как я уже сказал, со временем будет расширена в несколько раз.
ATM_info не таблица, а вьюшка. но там всего 1000 строк и она генерится за секунду.

Цитата: admin от 17 февраля  2015, 08:07:05  
Запрос нормально отрабатывает на самом сервере? За какое время?
Этот же запрос через Navicat также зависал. 

Цитата: Chernov от 20 февраля  2015, 04:11:57  
И вообще сделайте через темповую таблицу
Попробую сделать так.

Chernov

Проверьте наличие индекса по полю : itemid  , в таблице : zabbix.history_uint

d.pimkin


Яндекс.Метрика