Форум сайта python.su
0
Здравствуйте, ув форумчане!
Задачка следующая:
имеется файл (файл достаточно большой ~ 1 000 000 строк)
В каждой строке имеется id (причем не численный, а символьный вида ‘65s4dfg’) + другая информация, разделенная символом ‘;’
Делается выборка из ~5 000 id.
Результат обрабатывается на vps с не очень большим запасом оперативы.
Соответственно алгоритм работ следующий:
для каждого id выполняем поиск по строкам в виде
f=open('file.csv','r')
for line in f:
if id in line: (действие)
Все работает достаточно долго (даже прогресс бар сделал что бы отследить ситуацию) ~20 мин за круг.
Конечно можно все загрузить в оперативу (а если файл разрастется в 2-5-10-50-100-1000-n раз)
Какие есть варианты кроме построчного чтения строк?
Офлайн
221
читать кусок файла ( буфер ) в память и его обрабатывать там. Но это только в том случае если действительно это проблемное место. Иначе выигрыша не дает.
Офлайн
33
Код в теги.
neitroНа память тут нагрузки вообще не будет, благодаря итератору.
Результат обрабатывается на vps с не очень большим запасом оперативы.
neitro
f=open('file.csv','r')
for line in f:
if id in line: (действие)
neitroГрузи, ничего не изменится.
Конечно можно все загрузить в оперативу (а если файл разрастется в 2-5-10-50-100-1000-n раз)
neitroПредварительно разбить файл на части и обработать их параллельно, 1 процесс на ядро процессора.
Какие есть варианты кроме построчного чтения строк?
Офлайн
857
neitroСколько длится построчное чтение без действий?
Все работает достаточно долго
Офлайн
0
py.user.nextОколо минуты без операций проверки
Сколько длится построчное чтение без действий?
BudulianinЕсли я считываю построчно - то в буфер ничего не идет, но если я файл превращу в массив, то он скушает достаточно неплохо (насколько я понимаю).
На память тут нагрузки вообще не будет, благодаря итератору.
BudulianinТ.е. процессор должен быть с несколькими ядрами.
Предварительно разбить файл на части и обработать их параллельно, 1 процесс на ядро процессора.
JOHN_16
читать кусок файла ( буфер ) в память и его обрабатывать там. Но это только в том случае если действительно это проблемное место. Иначе выигрыша не дает.
Офлайн
33
Последний раз говорю, код в теги оберни.
neitro
Если я считываю построчно - то в буфер ничего не идет, но если я файл превращу в массив, то он скушает достаточно неплохо (насколько я понимаю).
С другой стороны: не перегоняя в массив я не могу обращаться поэлементно - поэтому метод половинного деления и т.д. использовать не получится.
neitroНе знаю, что у тебя за принцип, может быть он не правильный.
Да была мысль разбить его по частям по принципу 1-х нескольких символов, но как то это не правильно.
Офлайн
857
neitroВообще-то, csv нужно читать специальным модулем, потому что разделитель может появляться внутри поля в виде обычного символа.
Около минуты без операций проверки
Отредактировано py.user.next (Июль 15, 2015 09:40:31)
Офлайн
253
py.user.nextПоддержу. Задача совершенно не поставлена. Файл меняется или нет? Насколько часто запросы к нему будут возникать? Какие требования к времени выполнения запроса? Строки в файле одинаковой длины? А так конечно напрашивается перегнать его в sqlite и не морочиться.
Если размер растёт
Офлайн
0
BudulianinКод приведен для понимания, что я сделал - вопрос теоретический по большей части.
Последний раз говорю, код в теги оберни.
BudulianinНасколько я понимаю “тормоза” идут из за большого кол-ва операций сравнивания. У меня этих оперцаций для каждого id 1 000 000, если бы воспользоваться методом половинного деления кол-во операций уменьшиться до 20 операций за круг
Не знаю, что у тебя за принцип, может быть он не правильный.
То что предложил я - вполне логично и просто.
BudulianinНеправильно предположим, что разбиваем по 1-м 5-ти символам, т.е. получаем файлы вида ‘a1b2с.txt’, но где находятся id 2-3-4 символьные. Это сильно усложнит логику задачи. А при дальнейшем увеличении данных - еще на n частей
Не знаю, что у тебя за принцип, может быть он не правильный.
То что предложил я - вполне логично и просто.
doza_andРегулярность - произвольная (не более 20раз/месяц). Требования по времени - минимальное (как всегда).
Поддержу. Задача совершенно не поставлена. Файл меняется или нет? Насколько часто запросы к нему будут возникать? Какие требования к времени выполнения запроса? Строки в файле одинаковой длины? А так конечно напрашивается перегнать его в sqlite и не морочиться.
Офлайн
24
neitro
У меня этих оперцаций для каждого id 1 000 000, если бы воспользоваться методом половинного деления кол-во операций уменьшиться до 20 операций за круг
from random import choice from string import ascii_letters as l from string import digits as d import linecache import time # generate data for test def gen_data(): with open('data', 'w') as file: for i in range(999999): file.write('%s ; %s \n' % (''.join([choice(d+l) for _ in range(10)]), ''.join([choice(d+l) for _ in range(300)]))) file.close() # generate ids list to search for def gen_ids(): with open('ids', 'w') as file: for i in range(4999): line = linecache.getline('data', choice(range(999999))) file.write('%s\n' % line.split(' ;')[0]) file.close() start = time.time() counter = 0 ids = [x.strip() for x in open('ids', 'r')] with open('data', 'r') as file: for line in file: if line.split(' ;')[0] in ids: counter += 1 ids.remove(line.split(' ;')[0]) print(counter) print(time.time() - start) 4989 192.94302320480347
Отредактировано ayb (Июль 17, 2015 10:18:27)
Офлайн