Я работаю над сценарием, который мой товарищ по команде использовал для создания базы данных SQLite3 локально на своем компьютере. Я внес некоторые изменения, чтобы мы могли использовать его в нашем приложении Django для обновления базы данных новыми данными, загруженными пользователем. Приложение позволяет пользователю загружать ZIP-файл, содержащий несколько хорошо отформатированных CSV-файлов, и добавляет информацию из CSV-файлов в базу данных. Это соответствующие части кода:
update_db.py
import glob, sqlite3, pandas, timeit, re
def upload_files(csv_files):
conn = sqlite3.connect('/path/to/my_db.db')
c = conn.cursor()
added_tables = []
for row in c.execute("SELECT name FROM sqlite_master WHERE type='table'"):
table_name = re.sub(r'\W+', '', str(row))
added_tables.append(table_name)
for csv_filename in csv_files.namelist():
if csv_filename.endswith('.csv'):
csv_file = csv_files.open(csv_filename)
# extract team name from csv_file string, remove whitespace
table_name = csv_filename.rsplit('/',2)[1]
table_name = re.sub('[^\w+]', '', table_name)
try:
df = pandas.read_csv(csv_file, error_bad_lines=False)
df.to_sql(table_name, conn, if_exists='append', index=False)
if table_name not in added_tables:
# add necessary columns
c.execute('alter table ' + str(table_name) + ' add team_BASEDOWN integer;')
c.execute('alter table ' + str(table_name) + ' add team_FIELDPOSITION integer;')
c.execute('alter table ' + str(table_name) + ' add team_HEADCOACH text;')
c.execute('alter table ' + str(table_name) + ' add team_OFFCOOR text;')
c.execute('alter table ' + str(table_name) + ' add team_DEFFCOOR text;')
added_tables.append(table_name)
# set basedown
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 0 where pff_DOWN = 1 or (pff_DOWN = 2 and pff_DISTANCE <= 6);')
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 1 where pff_DOWN = 2 and pff_DISTANCE >= 7;')
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 2 where pff_DOWN = 3 and pff_DISTANCE <= 2;')
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 3 where pff_DOWN = 3 and pff_DISTANCE = 3;')
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 4 where pff_DOWN = 3 and pff_DISTANCE >= 4 and pff_DISTANCE <= 6;')
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 5 where pff_DOWN = 3 and pff_DISTANCE >= 7;')
c.execute('update ' + str(table_name) + ' set team_BASEDOWN = 6 where pff_DOWN = 4;')
# set fieldposition
c.execute('update ' + str(table_name) + ' set team_FIELDPOSITION = 0 where pff_FIELDPOSITION <= -1 and pff_FIELDPOSITION >= -10;')
c.execute('update ' + str(table_name) + ' set team_FIELDPOSITION = 1 where pff_FIELDPOSITION <= -11 or (pff_FIELDPOSITION >= 20 and pff_FIELDPOSITION <= 50);')
c.execute('update ' + str(table_name) + ' set team_FIELDPOSITION = 2 where pff_FIELDPOSITION >= 12 and pff_FIELDPOSITION <= 20;')
c.execute('update ' + str(table_name) + ' set team_FIELDPOSITION = 3 where pff_FIELDPOSITION >= 6 and pff_FIELDPOSITION <= 11;')
c.execute('update ' + str(table_name) + ' set team_FIELDPOSITION = 4 where pff_FIELDPOSITION <= 5;')
except pandas.errors.EmptyDataError as ex:
print(str(csv_file) + ' was empty; continuing...')
continue;
conn.commit()
conn.close()
views.py
from django.shortcuts import render
from django.db import connections
from django.db.utils import OperationalError
from django.http import HttpResponse
from django.template import loader
from django.conf import settings
from django.utils.encoding import smart_str
from webapp.update_db import upload_files
from threading import Thread
import numpy as np
import zipfile
def upload(request):
if request.method == 'POST' and request.FILES['myfile']:
myfile = request.FILES['myfile']
if str(myfile.name).endswith('.zip'):
unzipped = zipfile.ZipFile(myfile)
upload_files(unzipped)
return render(request, 'webapp/upload.html')
Моя проблема в том, что когда я отправляю zip-файл, загрузка занимает смехотворно много времени (примерно 12 часов при работе с zip-файлом размером 160 МБ). Я чувствую, что запросы SQL могли бы быть более эффективными, но он сказал, что когда он выполнялся локально, на создание всей базы данных ушло всего около 45 минут (что намного больше, чем мы ожидаем как «обновления»), поэтому мне интересно если что-то странное происходит с экземпляром EC2, на котором запущено приложение. Я проверил загрузку ЦП на экземпляре, и он показывает стабильное среднее значение 20% в течение времени, когда выполнялся скрипт обновления (никаких заметных всплесков или впадин). Я не уверен, что изменилось бы между локальным запуском экземпляра и запуском его в EC2, поэтому любые предложения по изменению экземпляра или сценария, которые улучшат производительность, будут с благодарностью приняты.