Mam kod, który wprowadza swoje dane i deklaruje go w słowniku. Obecnie mam długi czas w pętli, która ma około 200 000 tysięcy danych zajmujących około 2 godzin. A teraz myślę, co więcej, jeśli mam 2 miliony danych.

Oto mój dla pętli przykład (przepraszam za nazewnictwo zmiennych, to tylko mój przykładowy kod):

# Gets the data in database
data_list = self.my_service.get_database_list()

my_dict_list = {}

for item in data_list:
    primary_key = item.primarykey
    value = item.name + item.address + item.age

    my_dict_list[primary_key] = value

To jest mój model / db Get Code:

def get_database_list(self):
    return self.session.query(
        self.mapper.name,
        self.mapper.addreess,
        self.mapper.age,
        )

Mój silnik bazy danych jest innodb . Czy istnieje sposób, aby był nieco optymalizować lub pętlą przez DATA szybciej. Dziękuję za podzielenie się.

0
Bazinga 25 listopad 2013, 09:57

3 odpowiedzi

Najlepsza odpowiedź

Po pierwsze, wątpię w wąskie gardło (kilka godzin) leży w części Pythona. Możesz uzyskać pewne ulepszenia z generatorami i dict kompsurensions, ale przez ile? Poszukaj próbki na 200 000 wierszy:

import base64
import os
def random_ascii_string(srt_len):
    return base64.urlsafe_b64encode(os.urandom(3*srt_len))[0:srt_len]

>>> data = [{'id': x, 'name': random_ascii_string(10), 'age':'%s' % x,
             'address': random_ascii_string(20)} for x in xrange(2*10**5)]

Twoje podejście

>>> timeit.timeit("""
... from __main__ import data
... my_dict_list = {}
... for item in data:
...     my_dict_list[item['id']] = item['name'] + item['address'] + item['age']""",
...         number = 100)
16.727806467023015

Rozumienie listy

>>> timeit.timeit("from __main__ import data; "
...    "my_dict_list = { d['id']: d['name']+d['address']+d['age'] for d in data}",
...     number = 100)
14.474646358685249

Wątpię, abyś mógł znaleźć dwie godziny w tych optymalizacji. Twoje pierwsze zadanie jest znalezienie gardła. Radzę, aby spojrzeć na część swojej pracy MySQL i prawdopodobnie przenosi go do:

  • Użyj oddzielnego pliku Inno DB na stół
  • Użyj indeksów, jeśli pobieranie mniejszej części danych
  • Zrób pewne oceny po stronie DB, takie jak name + address + age
  • Nie dokonuj przetwarzania dla całych danych, pobieraj tylko potrzebną część (kilka pierwszych wierszy)
3
alko 25 listopad 2013, 06:30

Trudno zgadnąć, gdzie twój kod spędza najwięcej czasu. Najlepszą rzeczą do zrobienia jest uruchomienie go za pomocą CProfile i Sprawdź wyniki.

python -m cProfile -o prof <your_script> <args...>

Dotyczy to pliku o nazwie prof, który można zbadać na różne sposoby, których najfajniejszy jest używać runsnakerun.

Poza tym, poza górą głowy, Dict-Rozumienie jest często szybsze niż alternatywy:

my_dict_list = { item.primarykey: item.name + item.address + item.age }

Również nie jest dokładnie jasne, co robi item.name + item.address + item.age (czy są one wszystkie ciągi?), Ale jeśli możesz rozważyć zmianę struktury danych i przechowywać item zamiast tej połączonej wartości, może pomóc w dalszej części.

2
shx2 25 listopad 2013, 06:13

Zgodził się z powyższymi uwagami na temat Ieratorów. Możesz spróbować użyć ze zrozumienia słownika w miejscu pętli.

import uuid
import time

class mock:
    def __init__(self):
        self.name = "foo"
        self.address = "address"
        self.age = "age"
        self.primarykey = uuid.uuid4()

data_list = [mock() for x in range(2000000)]

my_dict_list = {}
t1 = time.time()
for item in data_list:
    primary_key = item.primarykey
    value = item.name + item.address + item.age
    my_dict_list[primary_key] = value
print(time.time() - t1)


my_dict_list = {}
t2 = time.time()
new_dict = { item.primarykey: item.name + item.address + item.age for item in data_list }
print(time.time() - t2)
0
Tim Wilder 25 listopad 2013, 06:45