Страница 1 из 4
Эффективность алгоритма
Добавлено: Пт дек 07, 2012 6:16 pm
Alex
Посмотрел я тут код и у меня возник вопрос. Выходит, что для получения каждой точки он (алгоритм) посылает отдельный SQL запрос. Если на графике 100 точек — это 100 SQL запросов. А если 200 точек, то это 200 SQL запросив. Если 10 графиков — это 2000(!) SQL запросов. Теперь понятно почему всё тормозит по жуткой силе.
Не лучше ли с точки зрения эффективности было бы делать 1 SQL запрос с времени start_time до времени end_time, а потом в цикле формировать DataSet? Вместо 2000 запросов будет всего 10.
Надо то всего написать один запрос и переписать цикл.
Код: Выделить всё
if ($total>0) {
$px=0;
$px_passed=0;
$dt=date('Y-m-d', $start_time);
while($start_time<$end_time) {
$ph=SQLSelectOne("SELECT ID, VALUE FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED<=('".date('Y-m-d H:i:s', $start_time)."') ORDER BY ADDED DESC LIMIT 1");
if ($ph['ID']) {
$values[]=(float)$ph['VALUE'];
} else {
$values[]=0;
}
if ($px_passed>40) {
if (date('Y-m-d',$start_time) != $dt) {
$hours[] = date('d/m',$start_time);
$dt = date('Y-m-d',$start_time);
} else {
$hours[] = date('H:i',$start_time);
}
$px_passed=0;
} else {
$hours[]='';
}
$start_time += $period;
$px += $px_per_point;
$px_passed += $px_per_point;
}
$DataSet->AddPoint($values,"Serie1");
$DataSet->AddPoint($hours,"Serie3");
} else {
$DataSet->AddPoint(0,"Serie1");
$DataSet->AddPoint(0,"Serie3");
}
Re: Эффективность алгоритма
Добавлено: Пт дек 07, 2012 6:52 pm
sergejey
Абсолютно согласен. Где-то в моём списке задач есть пункт про оптимизацию графиков именно в таком ключе -- один запрос и формирование точек с нужными интервалами уже по имеющейся выборке. Так что либо я со временем до этого пункта дойду, либо кто-то из тех кто может внести изменения в исходники и их прислать ))
Re: Эффективность алгоритма
Добавлено: Пт дек 07, 2012 7:10 pm
Alex
То ли я графики очень люблю,

то ли чего, но у меня система уже встала. Нажимаем на страничку и 20 секунд ждём отрисовки паршивенького графика. Я конечно попробую переписать этот кусок, но не уверен, что моих познаний будет достаточно. Ау, php программисты! Мы ищем таланты!

Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 12:02 pm
Alex
Итак,
выносим SQL запрос за пределы цикла, убираем лимит 1, меняем SQLSelectOne на mysql_query и добавляем строку с mysql_fetch_array. Всё.
Субъективно скорость при работе с графиками возрасла раз в десять(!). И загрузка системы упала раз в десять(!), правда у меня много графиков.
Специалистам по php надо проверить это изменение и добавить проверку на ошибки.
Старый код
Код: Выделить всё
while($start_time<$end_time) {
$ph=SQLSelectOne("SELECT ID, VALUE FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED<=('".date('Y-m-d H:i:s', $start_time)."') ORDER BY ADDED DESC LIMIT 1");
Новый код
Код: Выделить всё
$ph6=mysql_query("SELECT ID, VALUE FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED<=('".date('Y-m-d H:i:s', $start_time)."') ORDER BY ADDED DESC");
while($start_time<$end_time) {
$ph=mysql_fetch_array($ph6);
Кстати, а что это за функция такая SQLSelectOne, даже документации по ней не нашёл.
Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 12:56 pm
sergejey
Погоди-ка... и оно так работает? Как-то странно ))
просто у тебя получается, что условия выборки задаётся один раз и по идее каждый раз должно одно и то же в цикле возвращаться. в общем, я сейчас ещё посмотрю. может сам туплю ))
Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 1:09 pm
Alex
Погоди-ка... и оно так работает?

Это мне напомнило Ералаш "проверим делением"

Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 1:17 pm
sergejey
Я кажется понял почему оно работает и где подводные камни... В общем, при идеальной и равномерной записи в таблицу данных оно будет работать, но вот если данные сохраняются неравномерно, то уже могут пойти сбои. Я переделал алгоритм в графиках сейчас и вроде стало пошустрее, т.к. одним запросом делается выборка и потом уже в цикле идёт подгонка соответствия точек.
Смотри что получилось.
Убираем:
Код: Выделить всё
while($start_time<$end_time) {
$ph=SQLSelectOne("SELECT ID, VALUE FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED<=('".date('Y-m-d H:i:s', $start_time)."') ORDER BY ADDED DESC LIMIT 1");
if ($ph['ID']) {
$values[]=(float)$ph['VALUE'];
} else {
$values[]=0;
}
if ($px_passed>30) {
if (date('Y-m-d', $start_time)!=$dt) {
$hours[]=date('d/m', $start_time);
$dt=date('Y-m-d', $start_time);
} else {
$hours[]=date('H:i', $start_time);
}
$px_passed=0;
} else {
$hours[]='';
}
$start_time+=$period;
$px+=$px_per_point;
$px_passed+=$px_per_point;
}
Заменяем на:
Код: Выделить всё
$history=SQLSelect("SELECT ID, VALUE, UNIX_TIMESTAMP(ADDED) as UNX FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>=('".date('Y-m-d H:i:s', $start_time)."') AND ADDED<=('".date('Y-m-d H:i:s', $end_time)."') ORDER BY ADDED");
$total=count($history);
$itm=0;
for($i=0;$i<$total;$i++) {
$unx=$history[$i]['UNX'];
if ($unx>=$start_time || $i==0) {
$values[$itm]=(float)$history[$i]['VALUE'];
$itm++;
$start_time+=$period;
if ($px_passed>30) {
if (date('Y-m-d', $unx)!=$dt) {
$hours[]=date('d/m', $unx);
$dt=date('Y-m-d', $unx);
} else {
$hours[]=date('H:i', $unx);
}
$px_passed=0;
} else {
$hours[]='';
}
$px+=$px_per_point;
$px_passed+=$px_per_point;
}
}
Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 2:40 pm
Alex
Вопрос теоретический, но хочется всё таки разобраться для себя.
В общем, при идеальной и равномерной записи в таблицу данных оно будет работать, но вот если данные сохраняются неравномерно, то уже могут пойти сбои.
Что понимается под неравномерной записью данных в таблицу? И почему должны пойти сбои? Что тут имеется в виду.?
Дело в том, что я не изменял сам алгоритм в цикле (предполагаем, что он правильный). А функция mysql_query по запросу просто выдаёт массив отсортированных точек со времени start до текущего времени. Как записывались данные в таблицу и как выдавать запрос — это дело (и проблемы) движка базы данных, мы просто получаем отсортированный массив, который обрабатываем в цикле. Откуда возьмутся сбои (если их до сих пор не было)?
Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 3:49 pm
sergejey
Alex писал(а):Вопрос теоретический, но хочется всё таки разобраться для себя.
В общем, при идеальной и равномерной записи в таблицу данных оно будет работать, но вот если данные сохраняются неравномерно, то уже могут пойти сбои.
Что понимается под неравномерной записью данных в таблицу? И почему должны пойти сбои? Что тут имеется в виду.?
Дело в том, что я не изменял сам алгоритм в цикле (предполагаем, что он правильный). А функция mysql_query по запросу просто выдаёт массив отсортированных точек со времени start до текущего времени. Как записывались данные в таблицу и как выдавать запрос — это дело (и проблемы) движка базы данных, мы просто получаем отсортированный массив, который обрабатываем в цикле. Откуда возьмутся сбои (если их до сих пор не было)?
Имеющийся алгоритм разбивает промежуток времени на равные интервалы и берёт значение на начало каждого интервала. У тебя сделана выборка так, что значения должны быть так же равномерно сохранены в базе данных, в этом случае всё ок, но если, предположим, по каким-то причинам из 10 положенных за данный интервал значений в базе оказалось всего два (ну там не поступали данные по какой-то причине), то твой алгоритм выберет эти два единственных значения, независимо от того в какое время они происходили на всём интервале и разместит их в начале графика.
Re: Эффективность алгоритма
Добавлено: Сб дек 08, 2012 4:30 pm
Alex
если, предположим, по каким-то причинам из 10 положенных за данный интервал значений в базе оказалось всего два (ну там не поступали данные по какой-то причине), то твой алгоритм выберет эти два единственных значения, независимо от того в какое время они происходили на всём интервале и разместит их в начале графика.
Действительно, похоже это так. С этим моментом мне всё ясно.
На будущее. В некоторых случаях (например мониторинг качества сетевого напряжения) важно видеть всплески напряжения на графике. А наш алгоритм выбирает ближайшую точку к start time и, естественно, все пики пропускает. Мало того, раз от раза start time меняется и график, при обновлении, на том же участке меняет свой вид. Иногда кардинально, что не есть гут.
Бывает и обратная ситуация, когда сенсор выдаёт (по уважительной причине) редкие отклонения значения и график показывает всплески параметра, которых нет на самом деле. Тут нужен лёгкий усредняющий фильтр. Где нибудь в параметрах &mid=1.
А новый код сейчас попробую протестировать...