oronsultan Ответов: 1

Лучший алгоритм "проб и ошибок" для поиска первой строки с определенной датой в большом текстовом файле


Привет,
В нашей системе у нас есть несколько служб, каждая служба имеет папку журнала.
Журналы очень большие, могут заканчиваться 40 МБ-2 ГБ.
Каждая строка в журнале начинается с формата даты, например: 21.07.2020-16.40.22

Мы написали приложение, которое помогает нам искать между всеми папками все соответствующие строки
дана конкретная дата и время.
Допустим, я хочу извлечь все журналы с 12 октября 2020 года между 10:00-13:00,
Система сначала отфильтрует все журналы во всех папках в соответствии со временем создания и временем последней записи.
Затем для каждого отфильтрованного журнала мы ищем соответствующие строки в соответствии с временными рамками.
Дата строки проверяется следующим способом:

private bool IsLineInTimeFrame(long lineNumber, string filePath)
        {
            bool result = false;
            List<string> content = ReadSpecificLine(filePath, lineNumber).Split(' ').ToList();
            foreach (string piece in content)
            {
                //Use the Parse() method
                try
                {
                    var regex = new Regex(@"\b\d{2}\.\d{2}.\d{4}\b-[012]{0,1}[0-9].[0-6][0-9].[0-6][0-9]");
                    foreach (Match m in regex.Matches(piece))
                    {
                        DateTime dt;
                        if (DateTime.TryParseExact(m.Value, "dd.MM.yyyy-HH.mm.ss", null, DateTimeStyles.None, out dt))
                        {
                            Logger.LogWriter.LogInstance.LogWrite($"{m.Value}");
                            if (dt >= Convert.ToDateTime(SelectedDateFrom) && dt <= Convert.ToDateTime(SelectedDateTo))
                            {
                                return true;
                            }
                        }
                    }
                }
                catch (Exception ex){}
            }
            return result;
        }

        string ReadSpecificLine(string filePath, long lineNumber)
        {
            string content = null;
            try
            {
                using (StreamReader file = new StreamReader(filePath))
                {
                    for (int i = 1; i < lineNumber; i++)
                    {
                        file.ReadLine();

                        if (file.EndOfStream)
                        {
                            Logger.LogWriter.LogInstance.LogWarning($"End of file. The file only contains {i} lines.");
                            break;
                        }
                    }
                    content = file.ReadLine();
                }
            }
            catch (IOException ex)
            {
                Logger.LogWriter.LogInstance.LogError(ex);
            }
            return content;
        }

Ноэ вот в чем вопрос:
Предполагая, что у нас есть 150 тысяч (или даже больше) строк, каков наилучший способ поиска первой строки, начинающейся с заданной даты и времени, без итерации по всему файлу?

Что я уже пробовал:

...................................................................

BillWoodruff

есть ли у вас контроль над тем, как структурированы журналы ?

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

не зная структуры журнала и не видя примера записи в журнале ... не могу сказать больше.

подумайте о проблеме проверки каждой строки/записи ... ошибки будут случаться.

PIEBALDconsult

1) Используйте правильный формат даты гггг-ММ-ДД (ISO 8601).
2) если требуется поиск, то вам нужно встроить его в механизм регистрации, а не добавлять его как запоздалую мысль.
3) иметь один набор журналов в день. Включите дату в имя файла журнала.
4) Если вам действительно нужно, то при архивировании журналов предыдущих дней вы можете добавить некоторую форму индексации для архива.
5) В общем, сделайте как можно больше работы заранее, чтобы уменьшить объем работы, необходимый позже.

6) рассмотрите возможность входа в SPLUNK, а не в файлы. Или загрузите файлы в SPLUNK для архивирования.

1 Ответов

Рейтинг:
0

CPallini

Предполагая, что журналы упорядочены по времени (как и должно быть), вы можете выполнить двоичный поиск[^].


BillWoodruff

#1 "должно быть" ... как ты думаешь, почему я спросил об этом оперативника ? Ссылка на язык агностик сортирует Википедию ... одна ссылка на .NET находится в самом конце этой очень длинной статьи.

ОП будет лучше знать, что "идея сортировки списка предметов для более быстрого поиска восходит к древности. Самым ранним известным примером является табличка Инакибит-Ану из Вавилона, датируемая примерно 200 годом до нашей эры. Табличка содержала около 500 шестидесятеричных чисел и их обратные числа, отсортированных в лексикографическом порядке, что облегчало поиск конкретной записи."

CPallini

Журналы, как правило, являются.
Меня нисколько не волнует, почему вы об этом спросили.
Кстати, спасибо.