Итак, у меня есть файл размером 1 ГБ в формате CSV, например, который я преобразовал в базу данных SQLite3
column1;column2;column3
1212;abcd;20090909
1543;efgh;20120120
За исключением того, что у меня 12 столбцов. Теперь мне нужно прочитать и отсортировать эти данные и переформатировать их для вывода, но когда я пытаюсь это сделать, мне кажется, что у меня заканчивается ОЗУ (с использованием векторов). Я читаю его из SQLite и сохраняю каждую строку файла в структуре, которая затем передается обратно в deque. Как я уже сказал, у меня заканчивается память, когда использование оперативной памяти приближается к 2 ГБ, и приложение вылетает. Я попытался использовать STXXL, но, по-видимому, он не поддерживает векторы не POD-типов (поэтому это должны быть long int, double, char и т. Д.), И мой вектор состоит в основном из std :: string, некоторого boost :: date и одного double значение.
По сути, мне нужно сгруппировать все «строки» вместе, имеющие одинаковое значение в определенном столбце, другими словами, мне нужно отсортировать данные по одному столбцу, а затем работать с этим.
Любой подход к тому, как я могу читать во всем или, по крайней мере, сортировать это? Я бы сделал это с SQLite3, но это кажется трудоемким. Возможно я не прав.
Благодарю.
В порядке желательности:
std::string
— это требует дополнительного несмежного выделения, которое приведет к потере памяти. Предпочитаю встроенный массив символов, если длина ограниченаЕсли вы хотите придерживаться подхода SQLite3, я рекомендую использовать список вместо вектора, чтобы вашей операционной системе не приходилось находить 1 ГБ или более непрерывной памяти.
Если вы можете пропустить шаг SQLite3, вот как я бы решил эту проблему:
MyRow
), который имеет поле для каждого столбца в вашем наборе данных.std::list<MyRow>
где каждая строка в вашем наборе данных становится экземпляром MyRow
Я надеюсь, это поможет вам.
Существуют значительные накладные расходы для std::string
, Если твой struct
содержит std::string
для каждого столбца вы будете тратить много места на char *
указатели, malloc
заголовки и т. д.
Попробуйте разобрать все числовые поля сразу при чтении файла и сохранить их в своей структуре как ints
или что вам нужно.
Если ваш файл на самом деле содержит много числовых полей, как показано в примере, я ожидаю, что он будет использовать Меньше чем размер файла памяти после разбора.
Создайте структуру для ваших записей.
Запись должна иметь функции «упорядочивания» для полей, по которым нужно отсортировать.
Считайте файл как объекты и сохраните его в контейнере с возможностью произвольного доступа, например std::vector
или же std::array
,
Для каждого поля вы хотите отсортировать по:
Создать таблицу индексов, std::map
используя значение поля в качестве ключа и индекс записи в качестве значения.
Чтобы обработать поля по порядку, выберите свою таблицу индексов и выполните итерации по таблице индексов. Используйте поле значения (a.k.a. index), чтобы извлечь объект из контейнера объектов.
Если записи имеют фиксированную длину или могут быть преобразованы в фиксированную длину, вы можете записать объекты в двоичном виде в файл и поместить файл в разные записи. Используйте таблицу индексов, как указано выше, за исключением использования позиций файла вместо индексов.
Спасибо за ваши ответы, но я разобрался с очень быстрым и простым подходом.
Я позволил SQLite3 сделать эту работу за меня, задав ему следующий запрос:
SELECT * FROM my_table ORDER BY key_column ASC
Для файла размером 800 МБ это заняло около 70 секунд, а затем я получил все данные в моей программе на C ++, уже упорядоченные по столбцу, по которому я хотел их сгруппировать, и обработал столбец по одной группе за раз и вывел их по одному в желаемом формате вывода, сохраняя мою оперативную память свободной от перегрузки. Общее время операции около 200 секунд, что меня вполне устраивает.
Спасибо за ваше время.