Python работает медленнее при переходе по большому списку
В настоящее время я выбираю большой список строк из базы данных с помощью pyodbc. Затем результат копируется в большой список, а затем я пытаюсь выполнить итерацию по списку. Прежде чем я покину python и попытаюсь создать его на С#, я хотел знать, было ли что-то, что я делал неправильно.
clientItems.execute("Select ids from largetable where year =?", year);
allIDRows = clientItemsCursor.fetchall() #takes maybe 8 seconds.
for clientItemrow in allIDRows:
aID = str(clientItemRow[0])
# Do something with str -- Removed because I was trying to determine what was slow
count = count+1
Дополнительная информация:
- Цикл for в настоящее время работает со скоростью около 5 циклов в секунду, и это кажется мне безумно медленным.
- Всего выделенных строк составляет ~ 489 000.
- Аппарат, на котором работает, имеет много оперативной памяти и процессора. Кажется, что работает только один или два ядра, а ram - 1,72 ГБ 4 ГБ.
Может ли кто-нибудь сказать мне, что случилось? Сценарии запускаются медленно?
Спасибо
Ответы
Ответ 1
Это не должно быть медленным с родными списками Python, но, возможно, драйвер ODBC возвращает "ленивый" объект, который пытается быть умным, но просто становится медленным. Попробуйте просто сделать
allIDRows = list(clientItemsCursor.fetchall())
в вашем коде и опубликовать дополнительные тесты.
(списки Python могут замедляться, если вы начинаете вставлять вещи в свою середину, но просто перебирать по большому списку нужно быстро)
Ответ 2
Он, вероятно, медленный, потому что вы сначала загружаете весь результат в память и выполняете итерацию по списку. Вместо этого попробуйте выполнить итерацию курсора.
И нет, сценарии не должны быть , которые медленнее.
clientItemsCursor.execute("Select ids from largetable where year =?", year);
for clientItemrow in clientItemsCursor:
aID = str(clientItemrow[0])
count = count + 1
Ответ 3
Здесь нужно больше исследований... рассмотрим следующий script:
bigList = range(500000)
doSomething = ""
arrayList = [[x] for x in bigList] # takes a few seconds
for x in arrayList:
doSomething += str(x[0])
count+=1
Это почти то же самое, что и ваш script, за вычетом базы данных, и занимает несколько секунд, чтобы работать на моей не ужасно быстрой машине.
Ответ 4
Когда вы напрямую подключаетесь к своей базе данных (я имею в виду, что вы получаете запрос SQL), сколько секдов выполняет этот запрос?
Когда запрос заканчивается, вы получите сообщение следующего вида:
NNNNN rows in set (0.01 sec)
Итак, если это время настолько велико, и ваш запрос медленный, как "native", возможно, вам нужно создать индекс в этой таблице.
Ответ 5
Это медленно, потому что вы
- Получение всех результатов
- Выделение памяти и присвоение значений этой памяти для создания списка allIDRows
- Итерация по этому списку и подсчет.
Если выполнение возвращает вернувшийся курсор, используйте курсор для этого преимущества и начинайте подсчет, когда вы возвращаете материал и экономя время на распределении памяти.
clientItemsCursor.execute("Select ids from largetable where year =?", year);
for clientItemrow in clientItemsCursor:
count +=1
Другие советы:
- создать индекс в год
- используйте 'select count (*) from..., чтобы получить счет за год', вероятно, это будет оптимизировано на db.
- Удалите строку aID, если это не нужно, это преобразование первого элемента строки в строку, даже если оно не используется.