Вертим логи как хотим ― анализ журналов в системах Windows
Пора поговорить про удобную работу с логами, тем более что в Windows есть масса неочевидных инструментов для этого. Например, Log Parser, который порой просто незаменим.
В статье не будет про серьезные вещи вроде Splunk и ELK (Elasticsearch + Logstash + Kibana). Сфокусируемся на простом и бесплатном.
Журналы и командная строка
До появления PowerShell можно было использовать такие утилиты cmd как find и findstr. Они вполне подходят для простой автоматизации. Например, когда мне понадобилось отлавливать ошибки в обмене 1С 7.7 я использовал в скриптах обмена простую команду:
findstr "Fail" *.log >> fail.txt
Она позволяла получить в файле fail.txt все ошибки обмена. Но если было нужно что-то большее, вроде получения информации о предшествующей ошибке, то приходилось создавать монструозные скрипты с циклами for или использовать сторонние утилиты. По счастью, с появлением PowerShell эти проблемы ушли в прошлое.
Основным инструментом для работы с текстовыми журналами является командлет Get-Content, предназначенный для отображения содержимого текстового файла. Например, для вывода журнала сервиса WSUS в консоль можно использовать команду:
Get-Content -Path 'C:\Program Files\Update Services\LogFiles\SoftwareDistribution.log' | Out-Host -Paging
Для вывода последних строк журнала существует параметр Tail, который в паре с параметром Wait позволит смотреть за журналом в режиме онлайн. Посмотрим, как идет обновление системы командой:
>Get-Content -Path "C:\Windows\WindowsUpdate.log" -Tail 5 -Wait

Смотрим за ходом обновления Windows.
Если же нам нужно отловить в журналах определенные события, то поможет командлет Select-String, который позволяет отобразить только строки, подходящие под маску поиска. Посмотрим на последние блокировки Windows Firewall:
Select-String -Path "C:\Windows\System32\LogFiles\Firewall\pfirewall.log" -Pattern 'Drop' | Select-Object -Last 20 | Format-Table Line

Смотрим, кто пытается пролезть на наш дедик.
При необходимости посмотреть в журнале строки перед и после нужной, можно использовать параметр Context. Например, для вывода трех строк после и трех строк перед ошибкой можно использовать команду:
Select-String 'C:\Windows\Cluster\Reports\Cluster.log' -Pattern ' err ' ‑Context 3
Оба полезных командлета можно объединить. Например, для вывода строк с 45 по 75 из netlogon.log поможет команда:
Get-Content 'C:\Windows\debug\netlogon.log' | Select-Object -First 30 -Skip 45
Журналы системы ведутся в формате .evtx, и для работы с ними существуют отдельные командлеты. Для работы с классическими журналами («Приложение», «Система», и т.д.) используется Get-Eventlog. Этот командлет удобен, но не позволяет работать с остальными журналами приложений и служб. Для работы с любыми журналами, включая классические, существует более универсальный вариант ― Get-WinEvent. Остановимся на нем подробнее.
Для получения списка доступных системных журналов можно выполнить следующую команду:
Get-WinEvent -ListLog *

Вывод доступных журналов и информации о них.
Для просмотра какого-то конкретного журнала нужно лишь добавить его имя. Для примера получим последние 20 записей из журнала System командой:
Get-WinEvent -LogName 'System' -MaxEvents 20

Последние записи в журнале System.
Для получения определенных событий удобнее всего использовать хэш-таблицы. Подробнее о работе с хэш-таблицами в PowerShell можно прочитать в материале Technet about_Hash_Tables.
Для примера получим все события из журнала System с кодом события 1 и 6013.
Get-WinEvent -FilterHashTable @
В случае если надо получить события определенного типа ― предупреждения или ошибки, ― нужно использовать фильтр по важности (Level). Возможны следующие значения:
- 0 ― всегда записывать;
- 1 ― критический;
- 2 ― ошибка;
- 3 ― предупреждение;
- 4 ― информация;
- 5 ― подробный (Verbose).
Собрать хэш-таблицу с несколькими значениями важности одной командой так просто не получится. Если мы хотим получить ошибки и предупреждения из системного журнала, можно воспользоваться дополнительной фильтрацией при помощи Where-Object:
Get-WinEvent -FilterHashtable @ | Where-Object -FilterScript

Ошибки и предупреждения журнала System.
Аналогичным образом можно собирать таблицу, фильтруя непосредственно по тексту события и по времени.
Подробнее почитать про работу обоих командлетов для работы с системными журналами можно в документации PowerShell:
PowerShell ― механизм удобный и гибкий, но требует знания синтаксиса и для сложных условий и обработки большого количества файлов потребует написания полноценных скриптов. Но есть вариант обойтись всего-лишь SQL-запросами при помощи замечательного Log Parser.
Работаем с журналами посредством запросов SQL
Утилита Log Parser появилась на свет в начале «нулевых» и с тех пор успела обзавестись официальной графической оболочкой. Тем не менее актуальности своей она не потеряла и до сих пор остается для меня одним из самых любимых инструментов для анализа логов. Загрузить утилиту можно в Центре Загрузок Microsoft, графический интерфейс к ней ― в галерее Technet. О графическом интерфейсе чуть позже, начнем с самой утилиты.
О возможностях Log Parser уже рассказывалось в материале «LogParser — привычный взгляд на непривычные вещи», поэтому я начну с конкретных примеров.
Для начала разберемся с текстовыми файлами ― например, получим список подключений по RDP, заблокированных нашим фаерволом. Для получения такой информации вполне подойдет следующий SQL-запрос:
SELECT extract_token(text, 0, ' ') as date, extract_token(text, 1, ' ') as time, extract_token(text, 2, ' ') as action, extract_token(text, 4, ' ') as src-ip, extract_token(text, 7, ' ') as port FROM 'C:\Windows\System32\LogFiles\Firewall\pfirewall.log' WHERE action='DROP' AND port='3389' ORDER BY date,time DESC
Посмотрим на результат:

Смотрим журнал Windows Firewall.
Разумеется, с полученной таблицей можно делать все что угодно ― сортировать, группировать. Насколько хватит фантазии и знания SQL.
Log Parser также прекрасно работает с множеством других источников. Например, посмотрим откуда пользователи подключались к нашему серверу по RDP.
Работать будем с журналом TerminalServices-LocalSessionManager\Operational.
Не со всеми журналами Log Parser работает просто так ― к некоторым он не может получить доступ. В нашем случае просто скопируем журнал из %SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational.evtx в %temp%\test.evtx.
Данные будем получать таким запросом:
SELECT timegenerated as Date, extract_token(strings, 0, '|') as user, extract_token(strings, 2, '|') as sourceip FROM '%temp%\test.evtx' WHERE EventID = 21 ORDER BY Date DESC

Смотрим, кто и когда подключался к нашему серверу терминалов.
Особенно удобно использовать Log Parser для работы с большим количеством файлов журналов ― например, в IIS или Exchange. Благодаря возможностям SQL можно получать самую разную аналитическую информацию, вплоть до статистики версий IOS и Android, которые подключаются к вашему серверу.
В качестве примера посмотрим статистику количества писем по дням таким запросом:
SELECT TO_LOCALTIME(TO_TIMESTAMP(EXTRACT_PREFIX(TO_STRING([#Fields: date-time]),0,'T'), 'yyyy-MM-dd')) AS Date, COUNT(*) AS [Daily Email Traffic] FROM 'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\MessageTracking\*.LOG' WHERE (event-id='RECEIVE') GROUP BY Date ORDER BY Date ASC
Если в системе установлены Office Web Components, загрузить которые можно в Центре загрузки Microsoft, то на выходе можно получить красивую диаграмму.

Выполняем запрос и открываем получившуюся картинку…

Любуемся результатом.
Следует отметить, что после установки Log Parser в системе регистрируется COM-компонент MSUtil.LogQuery. Он позволяет делать запросы к движку утилиты не только через вызов LogParser.exe, но и при помощи любого другого привычного языка. В качестве примера приведу простой скрипт PowerShell, который выведет 20 наиболее объемных файлов на диске С.
$LogQuery = New-Object -ComObject "MSUtil.LogQuery" $InputFormat = New-Object -ComObject "MSUtil.LogQuery.FileSystemInputFormat" $InputFormat.Recurse = -1 $OutputFormat = New-Object -ComObject "MSUtil.LogQuery.CSVOutputFormat" $SQLQuery = "SELECT Top 20 Path, Size INTO '%temp%\output.csv' FROM 'C:\*.*' ORDER BY Size DESC" $LogQuery.ExecuteBatch($SQLQuery, $InputFormat, $OutputFormat) $CSV = Import-Csv $env:TEMP'\output.csv' $CSV | fl Remove-Item $env:TEMP'\output.csv' $LogQuery=$null $InputFormat=$null $OutputFormat=$null
Ознакомиться с документацией о работе компонента можно в материале Log Parser COM API Overview на портале SystemManager.ru.
Благодаря этой возможности для облегчения работы существует несколько утилит, представляющих из себя графическую оболочку для Log Parser. Платные рассматривать не буду, а вот бесплатную Log Parser Studio покажу.

Интерфейс Log Parser Studio.
Основной особенностью здесь является библиотека, которая позволяет держать все запросы в одном месте, без россыпи по папкам. Также сходу представлено множество готовых примеров, которые помогут разобраться с запросами.
Вторая особенность ― возможность экспорта запроса в скрипт PowerShell.
В качестве примера посмотрим, как будет работать выборка ящиков, отправляющих больше всего писем:
Выборка наиболее активных ящиков.
При этом можно выбрать куда больше типов журналов. Например, в «чистом» Log Parser существуют ограничения по типам входных данных, и отдельного типа для Exchange нет ― нужно самостоятельно вводить описания полей и пропуск заголовков. В Log Parser Studio нужные форматы уже готовы к использованию.
Помимо Log Parser, с логами можно работать и при помощи возможностей MS Excel, которые упоминались в материале «Excel вместо PowerShell». Но максимального удобства можно достичь, подготавливая первичный материал при помощи Log Parser с последующей обработкой его через Power Query в Excel.
Приходилось ли вам использовать какие-либо инструменты для перелопачивания логов? Поделитесь в комментариях.
Загрузка логов журнала регистрации 1С из MS SQL в ElasticSearch
В данной статье покажу еще один инструмент хранения и визуализации записей журнала регистрации 1С.
Входная задача: Небольшая конфигурация на 1С Предприятие 8.2. Максимальная суточная активность — 150 чел. Информационная база генерирует ~ 0,5 млн записей логов в рабочие дни. Логи необходимо хранить в сторонней БД MS SQL. Также необходим гибкий инструмент хранения и визуализации логов, как текущего так и прошлого периода (3-5 лет). Использовать стек ELK (Elastic + Logstash + Kibana).
Решение: Будет реализована следующая инфраструктура:

Последовательность действий:
1. Запись журнала регистрации 1С в базу MS SQL;
2. Отправка логов 1С из MS SQL в ElastisSearch;
3. Визуализация логов 1С в Kibana.
Реализация.
Запись журнала регистрации 1С в базу MS SQL
Механизм реализовал Алексей Бочков, описание и исходники в статье //infostart.ru/public/182820/
Для того, чтобы Logstash понимал, какие записи уже были отправлены в Elastic, а какие появились с момента последнего запуска — необходимо в таблице Events создать инкрементное поле id_log типа bigint (+ 8 байт на запись). Для этого в MS SQL Server Management Studio достаточно выполнить запрос:
USE [log1c] ALTER TABLE [log1c].[dbo].[Events] ADD id_log bigint identity
где log1c — имя базы данных с логами.
В итоге, имеем базу данных MS SQL с актуальными логами информационной базы 1С, которые периодически считываются из файла ЖР.
Отправка логов 1С из MS SQL в ElastisSearch
На том, как устанавливать стек ELK (Elastic + Logstash + Kibana) останавливаться не буду, т.к. в Интернет есть много подробной информации. Например, jdbc-input-plugin.
На сервере Logstash внесем изменения в конфигурационный файл
input < jdbc < jdbc_driver_library =>"C:\logstash-2.3.4\jdbc2\sqljdbc_4.2\rus\sqljdbc41.jar" jdbc_driver_class => "com.microsoft.sqlserver.jdbc.SQLServerDriver" jdbc_connection_string => "jdbc:sqlserver://10.4.2.147\MSSQLSERVER:1433;DatabaseName=log1c" jdbc_user => "logstash" jdbc_password => "Qwerty123" jdbc_fetch_size => "100000" #clean_run => true last_run_metadata_path => "C:\logstash-2.3.4\last_run\last_run" statement_filepath => "C:\logstash-2.3.4\bin\SQLQuery.sql" schedule => "* * * * *" tracking_column => id_log use_column_value => true > > filter < date< target =>"datetime" match => ["datetime", "YYYY-MM-dd HH:mm:ss.SSS", "MMM dd YYYY HH:mm:ss.SSS", "ISO8601"] > > output < elasticsearch < hosts =>"10.4.2.90:9200" index => "log1c-%" > >
Разберем настройки подробнее.
jdbc_driver_library — путь к библиотеке jdbc драйвера, скачиваем с
jdbc_connection_string => «jdbc:sqlserver://10.4.2.147\MSSQLSERVER:1433;DatabaseName=log1c» — 10.4.2.147 — IP адрес сервера MSSQL, MSSQLSERVER — Instance Name заданный при установке, 1433 — порт, log1c — БД с логами.
jdbc_user, jdbc_password — логин/пароли для доступа к БД
jdbc_fetch_size — размер выборки из БД
tracking_column — имя колонки, значение которой будет отслеживаться (то самое инкрементное поле id_log)
last_run_metadata_path — путь к файлу, где храниться значение отслеживаемой колонки
use_column_value => true — включаем использование отслеживаемого столбца (на запрос будет добавляться условие Where, в параметр sql_last_value будет вставлено значение из файла last_run_metadata_path)
statement_filepath => «C:\logstash-2.3.4\bin\SQLQuery.sql» — путь к файлу с запросом SQL
schedule => «* * * * *» — расписание, периодического выполнения запроса к БД, в формате Cron.
Текст запроса в файле «C:\logstash-2.3.4\bin\SQLQuery.sql»
SELECT e.* ,i.[Name] AS "InfobaseName" ,a.[Name] AS "AppName_str" ,c.[Name] AS "ComputerName_str" ,et.[Name] AS "EventName" ,mp.[Name] AS "MainPorts" ,sp.[Name] AS "SecondPortsName" ,md.[Name] AS "MetadataName" ,md.[Guid] AS "MetadataGUID" ,s.[Name] AS "ServerName" ,u.[Name] AS "UserName_str" ,u.[Guid] AS "UserGUID" ,FORMAT(e.[datetime], 'yyyy-MM', 'en-US') as 'index_elastic' FROM [log1c].[dbo].[Events] e left join [log1c].[dbo].[Infobases] i ON (e.[InfobaseCode] = i.[Code]) left join [log1c].[dbo].[Applications] a ON (e.[InfobaseCode] = a.[InfobaseCode] AND e.[AppName] = a.[Code]) left join [log1c].[dbo].[Computers] c ON (e.[InfobaseCode] = c.[InfobaseCode] AND e.[ComputerName] = c.[Code]) left join [log1c].[dbo].[EventsType] et ON (e.[InfobaseCode] = et.[InfobaseCode] AND e.[EventID] = et.[Code]) left join [log1c].[dbo].[MainPorts] mp ON (e.[InfobaseCode] = mp.[InfobaseCode] AND e.[MainPortID] = mp.[Code]) left join [log1c].[dbo].[SecondPorts] sp ON (e.[InfobaseCode] = sp.[InfobaseCode] AND e.[SecondPortID] = sp.[Code]) left join [log1c].[dbo].[Metadata] md ON (e.[InfobaseCode] = md.[InfobaseCode] AND e.[MetadataID] = md.[Code]) left join [log1c].[dbo].[Servers] s ON (e.[InfobaseCode] = s.[InfobaseCode] AND e.[ServerID] = s.[Code]) left join [log1c].[dbo].[Users] u ON (e.[InfobaseCode] = u.[InfobaseCode] AND e.[UserName] = u.[Code]) WHERE e.id_log > :sql_last_value
Итого, при первом запуске Logstash в Elastic выгрузятся все записи из БД log1c (sql_last_value=0), при последующем запуске будут считываться только вновь добавленные записи (последнее считанное значение id_log будет храниться в файле last_run_metadata_path и передаваться в качестве переменной через sql_last_value)
Визуализация логов 1С в Kibana
Если ElasticSearch и Kibana установлены на одном сервере, то дефолтных настроек будет достаточно. В нашем случае — на разных серверах, поэтому необходимо внести правки в конфигурационные файлы.
Для ElasticSearch в файл elasticsearch.yml
network.host: ["127.0.0.1", "10.4.2.90"] network.port: 9200 discovery.zen.ping.unicast.host: [IP_адреса]
Для Kibana — файл kibana.yml
server.port: 5601 server.host: "10.4.2.91" elasticsearch.url: "10.4.2.90:9200"
Самая приятная часть — анализ и визуализация логов. Вводим в браузере «10.4.2.91:5601», на вкладке Settings создаем новый шаблон индекса:

На вкладке Discover появятся все логи журнала регистрации 1С:

Запрос на сервер Elastic для отбора всех ошибок ЖР:
Все поиски и визуализации можно вывести на dashboard, задать период анализа логов (например за последний час) и частоту обновления из Elastic.

Возможности резервного копирования и восстановления в ElasticSearch реализованы очень интересно. Управление через HTTP запросы в формате JSON.
Сначала, необходимо создать репозиторий.
curl -XPUT 'http://l0.4.2.90:9200/_snapshot/backup1' -d ' < "type": "fs", "settings": < "location": "/elastic-backup", "compress": true >>'
где type — тип хранилища, куда будут складываться бэкапы. Для дефолтной установки доступна только файловая система. С дополнительными плагинами можно реализовать хранение на Azure Cloud, HDFS и AWS S3.
location — путь хранения
compress — сжимать ли бэкапы, по умолчанию true.
Репозиторий создан, можно бэкариповать — создадим snapshot1 в репозитории backup1:
curl -XPUT "10.4.2.90:9200/_snapshot/backup1/snapshot1?wait_for_completion=true"
Для восстановления данных:
curl -XPOST "10.4.2.90:9200/_snapshot/backup1/snapshot1/_restore"
Посмотреть текущие индексы:
curl -XGET "10.4.2.90:9200/_cat/indices/?pretty"
Удалить индекс «log1c-2014-02» — все логи за февраль 2014 г.:
curl -XDELETE "10.4.2.90:9200/log1c-2014-02/?pretty"
Более полный список команд по работе с ElasticSearch — тема для отдельной статьи.
Замечания:
1) В данной статье не рассматриваются вопросы безопасности/разграничения доступа к ElasticSearch/Kibana, настройка сертификатов, кластеризация и масштабирование ElasticSearch, т.к. это не входило в изначальную задачу.
2) Выбранная архитектура миграции логов 1С -> MS SQL -> ELK обусловлена только лишь поставленной задачей. В Production логи не будут храниться в БД и ElasticSearch, дублирую друг друга.
3) Размер БД в 500 ГБ уже требует большого количества ресурсов и операций чтения с диска при выполнении запроса от Logstash к MS SQL. Можно было бы на MS SQL создать архивную БД, в которую выгружать прочитанные Logstash’ом данные. Тогда таблица, в которую пишутся данные из 1С и читаются в Logstash, будет иметь небольшой объем (буфер).
Итоги по задаче. В ходе выполнения задачи, была достигнута главная цель статьи — демонстрация механизма получения и анализа данных в ElasticSearch из БД MS SQL.
P.S. Возможно, вам будет интересна предыдущая статья Мониторинг количества сеансов 1С на базе PRTG
Периодическая загрузка событий из журналов регистрации в базу MS SQL Server (с исходниками)
Еще один вариант парсера файлов журнала регистрации для 8.2.
Преимущества:
1) Читает файлы напрямую, что дает высокую скорость.
2) Знает, где остановилось чтение в прошлый раз, и начинает с этого места при следующем запуске.
3) Может работать и как windows-служба, и как обычное приложение.
Скачать файлы
.zip 314,56Kb
Приложение написано на .NET 2.0.
Порядок работы:
1) На сервере MS SQL создать пустую базу данных. 2) На сервере приложений 1С, из БД которого нужно грузить события, под административными правами запустить EventLogLoaderManager.exe
3) Указать строку соединения с базой. Можно использовать шаблоны:
для windows-авторизации Data Source=MSSQL1;Server=имя сервера;Database=имя базы;Integrated Security=true;
для обычной авторизации Data Source=MSSQL1;Server=имя сервера;Database=имя базы;Password=Пароль;User пользователя; 4) Указать интервал между циклами чтения событий из ЖР. Допустимо ставить несколько секунд — на производительности сервера не скажется. 5) Отметить те БД, события из которых необходимо периодически загружать в базу. 6) Нажать «Сохранить параметры», при этом в каталоге программы создается файл настроек setting.ini 7) Если нужна периодическая загрузка – нажимаем «Установить службу», ищем в списке служб «EventLog loader service» и исправляем аккаунт, от имени которого будет работать служба. Если строка соединения содержит логин и пароль, то можно ничего не менять, если нет, то службу нужно запускать от имени правильной учетной записи windows, которая имеет полные права на SQL-базу с событиями. 8) Если нужна разовая загрузка – запускаем из каталога программы EventLogLoader.exe. Следует учесть, что это приложение, как и служба, работает в бесконечном цикле (проверяет новые события, пишет их в базу, делает паузу, затем повторяет заново), поэтому прерывается она при нажатии любой кнопки мыши. 
Некоторые особенности
1) Для каждой ИБ журнал регистрации грузится в отдельном потоке. Если начнете грузить по сотне баз, то велика вероятность на начальном этапе повесить сервер. В дальнейшем, если проверять новые события достаточно часто (например, каждые 10 секунд), то служба быстро их записывает в базу без особой загрузки сервера. 2) Если загрузку прервать, то при повторном запуске она продолжится с места остановки (позиция сохраняется в БД). 3) Таблицы в БД создаются автоматически. Если вы удалили какая-нибудь таблицу — надо перезапустить службу. 4) Все события по всем ИБ хранятся в одной таблице. Разделитель – колонка «Код информационной базы». 5) Логи с ошибками хранятся в каталоге программы в папке «log». 6) Работает только с платформой 8.2 (файлами lgf и lgp). 7) В таблицах созданы только основные кластерные индексы по полю «Код информационной базы». Для ускорения запросов, которые вам требуются регулярно, нужно добавлять свои индексы. 8) Несколько полей осталось нераспознанными (Field2, Field7, Field8). Если вам известно их назначение — сообщите, пожалуйста.
Описание таблиц
1) Infobases — список обрабатываемых ИБ. Код генерируется автоматически при добавлении новой базы в этот список. Эти же коды определяют принадлежность записей в определенной ИБ во всех других таблицах.
2) Params — хранит последние прочитанные файлы и позиции в них. 3) Назначение остальных таблиц понятно из их названия. Итоговая таблица с событиями с присоединенными справочниками SELECT TOP ( 1000 ) Infobases.Name , Events.DateTime , Events.TransactionStatus , Events.TransactionStartTime , Events.TransactionMark ,
Users.Name AS [ User ], Computers.Name AS Computer , Applications.Name AS App , Events.Field2 , EventsType.Name AS EventType ,
Events.EventType , Events.Comment , Metadata.Name AS Metadata , Events.DataStructure , Events.DataString ,
Servers.Name AS [ Server ], MainPorts.Name AS MainPort , SecondPorts.Name AS SecondPort , Events.Seance
FROM Events INNER JOIN
Applications ON Events.InfobaseCode = Applications.InfobaseCode AND Events.AppName = Applications.Code INNER JOIN
Computers ON Events.InfobaseCode = Computers.InfobaseCode AND Events.ComputerName = Computers.Code INNER JOIN
EventsType ON Events.InfobaseCode = EventsType.InfobaseCode AND Events.EventID = EventsType.Code INNER JOIN
Infobases ON Events.InfobaseCode = Infobases.Code INNER JOIN
Users ON Events.InfobaseCode = Users.InfobaseCode AND Events.UserName = Users.Code INNER JOIN
SecondPorts ON Events.InfobaseCode = SecondPorts.InfobaseCode AND Events.SecondPortID = SecondPorts.Code INNER JOIN
Servers ON Events.ServerID = Servers.Code AND Events.InfobaseCode = Servers.InfobaseCode INNER JOIN
MainPorts ON Events.InfobaseCode = MainPorts.InfobaseCode AND Events.MainPortID = MainPorts.Code INNER JOIN
Metadata ON Events.InfobaseCode = Metadata.InfobaseCode AND Events.MetadataID = Metadata.Code 
Объемы получаемой информации

Хранение структурированных данных более затратное с точки зрения требуемого места на дисках.
Иными словами — объем базы данных будет существенно больше суммы объемов всех ЖР, которые были обработаны и загружены. Реальный пример: 2 информационные базы с объемом ЖР 2132 Мб (1192+971). Время первичного разбора в 2 потока (т.к. базы 2) — около 1,5 часов. Общее количество событий — 19’507’484 млн. Объем базы на MS SQL Server — 12879 Мб, т.е. примерно в 6 раз больше! НО — если применить сжатие таблиц, как, например, описано здесь, то получим 1610 Мб, т.е. даже меньше исходных данных .
К сожалению, не все версии MS SQL Server поддерживают сжатие.



