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, если это не нужно, это преобразование первого элемента строки в строку, даже если оно не используется.