Re[42]: решение мойе задачи
От: Pavel Dvorkin Россия  
Дата: 05.10.09 04:49
Оценка:
PD>Дан файл в формате CSV. 10 полей на строчку, есть пустые поля. Поля не длинные, обычно 5-10 символов. Количество строк известно, порядка 5 миллионов. Размер файла 200 Мб, известен точно.

PD>Делай что хочешь, но должен обеспечить


PD>2. Выдачу строк, отсортированых по любому из первых трех полей. (SELECT * ORDER BY FIELD1)

PD>3. Выдачу любого набора полей в любом порядке из строк, отсортированных по любому из первых трех полей (SELECT FIELD2,FIELD5 ORDER BY FIELD1)
PD>4. Выдачу аналогично п.3, но только для тех строк, у которых поле сортировки равно чему-то (SELECT FIELD2,FIELD5 ORDER BY FIELD1 WHERE FIELD1="ABCD")

PD>Для п.2-4 сортировка в момент запроса не допускается. Данные должны быть готовы для выдачи в этот момент без какой бы то ни было модификации.


PD>Вся информация должна быть в ОП, чтение из файла можно провести только один раз.

PD>Можешь завести нужные вспомогательные структуры, массивы и т.п, но копировать строки не разрешается. Иными словами, каждая исходное текстовое поле должно присутствовать в памяти ТОЛЬКО ОДИН РАЗ. Хоть явно, хоть неявно. На вспомогательные структуры, так и быть, еще 50-70 Мб дам.

Заводим буфер длиной на 1 байт больше чем размер файла. Читаем файл в буфер целиком в двоичном виде.

Заводим три массива указателей p1,p2,p3 размером в количество строк (оно известно)

Проходим по буферу, заменяем запятые на нули. В конце строки нет запятой, но есть CR/LF. CR заменяем на 0, LF игнорируем.

(Осторожно! В самом конце файла может CR/LF не быть. Именно поэтому я задал буфер на 1 байт больше. Если это так, записываем 0 в конце)

По ходу этого прохода формируем массив p1 как массив указателей на начала строк как они были (и есть)

Копируем p1 в p2 и p3

Сортируем p1 , используя в качестве ключа первое текстовое поле. Там asciiz, так что используем стандартные qsort и strcmp

Сортируем p2 по второму, и p3 по третьему полю таким же образом. Поскольку у нас строки заканчиваются нулем, переход от одного поля к другому не вызывает проблем. Фактически мы здесь имеем почти multi-sz формат, только без завершающего нуля.

PD>1. Выдачу этих строк в исходном порядке


Пройти буфер подряд без использования этих указателей

PD>2. Выдачу строк, отсортированых по любому из первых трех полей. (SELECT * ORDER BY FIELD1)


Пройти буфер в порядке p1, p2 или p3

PD>3. Выдачу любого набора полей в любом порядке из строк, отсортированных по любому из первых трех полей (SELECT FIELD2,FIELD5 ORDER BY FIELD1)


Аналогично 2, но выбирать только нужные поля.

PD>4. Выдачу аналогично п.3, но только для тех строк, у которых поле сортировки равно чему-то (SELECT FIELD2,FIELD5 ORDER BY FIELD1 WHERE FIELD1="ABCD")


Провести двоичный поиск в массиве p1, p2 или p3 соответственно, найти начало и конец участка, соответствующего требуемому полю сортировки, далее аналогично 3.

Задача решается для любого размера как исходных строк, так и полей.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.