Ошибка #44
Необходимо уплотнять данные о трафике в базе
| Status: | Закрыт | Start date: | 2010-06-22 | |
|---|---|---|---|---|
| Priority: | Срочный | Due date: | 2010-09-06 | |
| Assignee: | % Done: | 100% |
||
| Category: | sql | |||
| Target version: | 0.1-beta |
Description
После запуска системы на реальном маршрутизаторе обслуживающем 60 - 70 машин которые имеют доступ к внешним ресурсам Интернета, база хранящая данные о трафике стала увеличиваться в размере очень быстро. За 3 - 4 часа ее размер стал равным 26 Мбайт. Очевидно, что такими темпами за неделю база перевалит за 1 Гбайт, а за месяц за 30 Гбайт. Это очень много.
На данный момент вижу следующее решение: периодически запускать уплотнение таблицы. Что это значит. За текущий месяц разрешение по трафику будет в один час. За предыдущие месяцы текущего года разрешение по трафику будет в одни сутки. За предыдущие годы разрешение по трафику будет в один год. То есть, по одному пользователю за предыдущий месяц информацию о трафике можно будет смотреть с разрешением в один день, текущий месяц - один час. Это позволит значительно сократить размер базы.
Related issues
| related to Улучшение #45: Изменить структуру хранения данных о трафике в базе | Закрыт | 2010-06-28 | 2010-07-30 | |
| related to Улучшение #52: Переработать скрипты выгрузки трафика | Закрыт | 2010-09-06 | 2010-09-09 | |
| related to Улучшение #4: Добавить скрипты обслуживающие базу данных. | Закрыт | 2010-03-07 | 2010-09-22 | |
| related to Улучшение #53: Добавить настройки в WEB-админку для опций хранения трафика | Закрыт | 2010-09-10 | 2010-10-13 |
History
Updated by Serg79 - over 1 year ago
Имеются следующие статистические данные:
За сутки работы системы база весит 48 Мбайт.
Число строк в таблице 'traffic' равен 304448.
За день к внешним ресурсам обращалось порядка 60 пользователей.
Плюс целую ночь раздавались торенты.
Updated by Serg79 - over 1 year ago
- Status changed from Новый to В работе
Updated by Роман Чернышов over 1 year ago
Может стоит сразу рассчитать минимальный необходимый интервал? Например, час. И либо на ходу суммировать, либо раз в сутки.
Updated by Serg79 - over 1 year ago
Собственно примерно думаю реализовать вот так.
У нас есть структура таблицы которая хранит информацию о трафике, назовем ее 'traffic':
create table `traffic` ( `date` datetime not null, `srcIp` int unsigned not null, `dstIp` int unsigned not null, `dstPort` int not null, `pId` tinyint not null, `inBytes` int unsigned not null, `outBytes` int unsigned not null, key `key1` (`date`), key `key2` (`srcIp`, `date`) ) engine = MyISAM;
Есть таблица trafficCurrent в которой будет храниться информация о трафике с разрешением в один час, т.е. детализация статистики по пользователю в один час. Эта таблица будет содержать данные о трафике только за текущий месяц, т.е. данные старше одного месяца будут удаляться из нее. Эта информация будет доступна например по ссылке "Текущая статистика" которая будет располагаться на главной странице "Статистики по месяцам".
Так же будут таблицы traffic2000, traffic2001, traffic2002 и т.д. в которых будут храниться данные о трафике за год. Но детализация о трафике в них будет в один месяц. Эта информация будет доступна через ссылки столбца "период" которые располагаются на главной странице "Статистика по месяцам". Эти таблицы, кроме таблицы в которую добавляется информация за текущий год, можно будет так же сжимать с помощью myisampack, что так же позволит уменьшить место занимаемое ими на диске.
Для работы с таблицами которые хранят данные за год создается служебная таблица 'periodTraffic':
create table `periodTraffic` ( `date` datetime not null, `tableName` char(10) not null, key `key1` (`date`) ) engine = MyISAM;
в которой храниться год и имя таблицы, которая хранит информацию о трафике за этот год.
Соответственно WEB-интерфейс статистики считывает данные из таблицы periodTraffic, далее выводит информацию о трафике считывая данные из соответствующих таблиц.
А параметр указывающий сколько лет хранить информацию о трафике будет задаваться через настройки WEB-интерфейса.
Как то так. У кого есть какие замечания или мысли по этому поводу высказывайтесь.
Updated by Serg79 - over 1 year ago
Роман Чернышов писал(а):
Может стоит сразу рассчитать минимальный необходимый интервал? Например, час. И либо на ходу суммировать, либо раз в сутки.
Сейчас так и делается, данные на ходу суммируются и если только нет записи о этом клиенте то данная запись добавляется:
...
# получим текущую дату
my ($sec,$min,$hour,$day,$mon,$year) =
localtime((@ARGV) ? time + ((shift @ARGV) * 60) : time);
$year += 1900; $mon++;
# Округлим значение времени до 30 минут. Это делается для того,
# что бы данные в базе были кратны одному часу. Это позволит
# базе данных быстрее работать с таблицей хранящей трафик.
$min = 30;
$sec = 0;
my $date = "$year-$mon-$day $hour:$min:$sec";
...
$query = 'insert into traffic ' .
'(date, srcIp, dstIp, dstPort, pId, inBytes, outBytes) ' .
'values(?, ?, ?, ?, ?, ?, ?)';
$sth = $dbh->prepare($query) or
error("Failed prepare query '$query': " . $dbh->errstr);
...
# добавим полученный трафик к уже имеющемуся в базе
$rv = $dbh->do(qq{update traffic set inBytes = inBytes + $inBytes, outBytes = outBytes + $outBytes
where date = '$date' && srcIp = '$srcIp' && dstIp = '$dstIp' && dstPort = '$dstPort' && pId = '$pId'}) or
error("Failed execute 'do' query: " . $dbh->errstr);
# если в базе еще нет записи о данном трафике, то добавим ее
if ($rv eq "0E0") {
$sth->execute($date, $srcIp, $dstIp, $dstPort, $pId, $inBytes, $outBytes) or
error("Failed execute query '$query': " . $dbh->errstr);
} elsif ($rv > 1) {
warning("When add data to the database updated more than one record ($rv).");
}
...
Updated by Serg79 - over 1 year ago
- % Done changed from 0 to 100
- Due date set to 2010-09-06
- Status changed from В работе to Закрыт
Committed in r112