Czemu baza danych musi być tak kretyńsko powolna?

0

Django, sqlite3. Napisałem skrypt by zaimportować dane z plików xls do bazy danych. W wyniku jego działania plik db.sqlite3 urósł do 14,3 MB. Czas działania skryptu – ok. 10 godzin. Czas importu danych z xls do słowników Pythona: ok. pół minuty. Czas kopiowania 14,3 MB danych na dysk: niemal natychmiast.

LOL? Jakie jest wyjaśnienie tej powolności? Czy to ja coś sp…, czy po prostu ma być tak powolna i koniec?

Po ch… mi baza danych, nie sprawdziłem tego ale stawiam nuts vs nuggets że wsadzenie tych danych do plików tekstowych i czytanie tych plików zamiast db byłoby jakieś 100 razy szybsze.

0

Pokaż ten skrypt, bo coś mi się wydaje, że tu leży problem i kretyńskie jest tutaj coś innego.

0

Zadanie akademickie…

Wiem, że nazewnictwo niektórych zmiennych jest do d…, usprawiedliwiam się tylko tym, że pisałem to ciężko w nocy.

Fakt, że zhardcodowałem podział województw na okręgi usprawiedliwiam tym, że tych danych nie było w plikach xls.

Pliki xls należało ściągnąć stąd: http://prezydent2000.pkw.gov.pl/gminy/obwody.html Pobrałem je na dysk.

Skrypt:

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'Wybory.settings'

import django
django.setup()

from WyboryApp.models import Województwo, Wyniki, Okręg, Gmina, Obwód, Kandydat, Głosy
from xlrd import open_workbook
from os.path import join, dirname
from itertools import islice

województwaNaOkręgi = {
    'dolnośląskie': [('Wrocław', 1), ('Jelenia Góra', 2), ('Legnica', 3), ('Wałbrzych', 4)],
    'kujawsko-pomorskie': [('Bydgoszcz', 5), ('Toruń', 6), ('Włocławek', 7)],
    'lubelskie': [('Lublin', 8), ('Biała Podlaska', 9), ('Chełm', 10), ('Puławy', 11), ('Zamość', 12)],
    'lubuskie': [('Zielona Góra', 13), ('Gorzów Wielkopolski', 14)],
    'łódzkie': [('Łódź', 15), ('Łódź', 16), ('Piotrków Trybunalski', 17), ('Sieradz', 18), ('Skierniewice', 19)],
    'małopolskie': [('Kraków', 20), ('Kraków', 21), ('Kraków', 22), ('Chrzanów', 23), ('Myślenice', 24),
                    ('Nowy Sącz', 25), ('Nowy Targ', 26), ('Tarnów', 27)],
    'mazowieckie': [('Warszawa', 28), ('Warszawa', 29), ('Ciechanów', 30), ('Legionowo', 31), ('Ostrołęka', 32),
                    ('Piaseczno', 33), ('Płock', 34), ('Radom', 35), ('Siedlce', 36)],
    'opolskie': [('Opole', 37), ('Opole', 38)],
    'podkarpackie': [('Rzeszów', 39), ('Krosno', 40), ('Przemyśl', 41), ('Tarnobrzeg', 42)],
    'podlaskie': [('Białystok', 43), ('Łomża', 44), ('Suwałki', 45)],
    'pomorskie': [('Gdańsk', 46), ('Gdańsk', 47), ('Słupsk', 48)],
    'śląskie': [('Katowice', 49), ('Bielsko-Biała', 50), ('Bytom', 51), ('Częstochowa', 52), ('Gliwice', 53),
                ('Sosnowiec', 54)],
    'świętokrzyskie': [('Kielce', 55), ('Kielce', 56)],
    'warmińsko-mazurskie': [('Olsztyn', 57), ('Elbląg', 58), ('Ełk', 59)],
    'wielkopolskie': [('Poznań', 60), ('Kalisz', 61), ('Konin', 62), ('Leszno', 63), ('Piła', 64)],
    'zachodniopomorskie': [('Szczecin', 65), ('Koszalin', 66), ('Stargard Szczeciński', 67), ('Szczecinek', 68)]
}

kandydaciNazwiska = [
    ('Dariusz Maciej', 'Grabowski'),
    ('Piotr', 'Ikonowicz'),
    ('Jarosław', 'Kalinowski'),
    ('Janusz', 'Korwin-Mikke'),
    ('Marian', 'Krzaklewski'),
    ('Aleksander', 'Kwaśniewski'),
    ('Andrzej', 'Lepper'),
    ('Jan', 'Łopuszański'),
    ('Andrzej Marian', 'Olechowski'),
    ('Bogdan', 'Pawłowski'),
    ('Lech', 'Wałęsa'),
    ('Tadeusz Adam', 'Wilecki')
]

print("Wyniki")
wyniki = Wyniki()
wyniki.save()

okręgi = {}

for woj in województwaNaOkręgi.items():
    print("Województwo ", "nazwa: ", woj[0])
    województwo = Województwo(nazwa=woj[0], wyniki=wyniki)
    województwo.save()
    for ok in woj[1]:
        print("Okręg ", "numer: ", ok[1], "miasto: ", ok[0], "województwo: ", województwo)
        okręg = Okręg(numer=ok[1], miasto=ok[0], województwo=województwo)
        okręg.save()
        okręgi[ok[1]] = okręg

kandydaci = []

for kand in kandydaciNazwiska:
    print("Kandydat ", "imię: ", kand[0], "nazwisko: ", kand[1])
    kandydat = Kandydat(imię=kand[0], nazwisko=kand[1])
    kandydat.save()
    kandydaci.append(kandydat)

gminy = {}

for i in range(1, 69):
    print("Okręg ", i)
    arkusz = open_workbook(join(dirname(__file__), 'dane', 'obw'+str(i).zfill(2)+'.xls')).sheet_by_index(0)
    wiersze = islice(arkusz.get_rows(), 1, None)
    for wiersz in wiersze:
        okręg = okręgi[int(wiersz[0].value)]
        kod_gminy = wiersz[1].value
        nazwa_gminy = wiersz[2].value
        powiat_gminy = wiersz[3].value
        print("Gmina ", "kod: ", kod_gminy, "nazwa: ", nazwa_gminy, "powiat: ", powiat_gminy)
        if kod_gminy not in gminy:
            gmina = Gmina(kod=kod_gminy, nazwa=nazwa_gminy, powiat=powiat_gminy)
            gmina.save()
        else:
            gmina = gminy[kod_gminy]
        gmina.okręg.add(okręg)
        gmina.save()
        numer_obwodu = int(wiersz[4].value)
        typ_obwodu = wiersz[5].value
        adres_obwodu = wiersz[6].value
        uprawnieni = int(wiersz[7].value)
        wydane = int(wiersz[8].value)
        oddane = int(wiersz[9].value)
        nieważne = int(wiersz[10].value)
        ważne = int(wiersz[11].value)
        print("Obwód ", "numer: ", numer_obwodu, "typ: ", typ_obwodu, "adres: ", adres_obwodu)
        obwód = Obwód(numer=numer_obwodu, typ=typ_obwodu, adres=adres_obwodu, gmina=gmina,
                      uprawnieni=uprawnieni, wydane=wydane, oddane=oddane,
                      nieważne=nieważne, ważne=ważne)
        obwód.save()
        for j in range(0, len(kandydaci)):
            głosy = Głosy(ilość=int(wiersz[12+j].value),
                          kandydat=kandydaci[j],
                          obwód=obwód)
            głosy.save()

Edit: Relacja między gminą a okręgiem jest niestety wiele do wielu. Model Głosy to liczba głosów na danego kandydata w danym obwodzie.

2

Nie znam pythona ale znam sql, najważniejsza optymalizacja w imporcie danych - nie rób insertu po jednym rekordzie ale np 200 rekordów za jednym zamachem. Importowałem kiedyś 2 miliony rekordów do bazy. Import po jednym rekordzie 30minut, import po 200 rekordach 1minuta.

0

Cóż, problem rozwiązany. Data migration w miejsce standalone skryptu działa w minutę. Nie mam pojęcia, dlaczego? Być może po części dlatego, że najpierw wszystko zczytuję do pamięci z plików xls, a potem z pamięci do bazy, czego nie robiłem w standalone skrypcie. Nie wiem, czemu działa, dość że działa. EDIT: I to pomimo, iż NIE używam transakcji ani bulk_create.

1 użytkowników online, w tym zalogowanych: 0, gości: 1