#python #mysql #sqlalchemy #query-optimization #large-data
#питон #mysql #sqlalchemy #оптимизация запросов #большие данные
Вопрос:
Я объясню структуру, которая у меня есть, но сначала я расскажу, что мне нужно. У меня есть таблица с прогнозами и одна с данными о том, что произошло на самом деле. И мне нужно вычислить forecast - happened
поле. В обеих таблицах есть поле координат (lon,lat), дата и количество осадков. У прогноза есть еще одно поле, которое является датой, когда был сделан прогноз.
class Real(Base):
__tablename__ = 'tbl_real'
id = Column(Integer, primary_key=True, autoincrement=True)
lon = Column(Integer,index=True)
lat = Column(Integer,index=True)
date = Column(DATE,index=True)
prec = Column(Integer)
class Forecast(Base):
__tablename__ = 'tbl_forecast'
id = Column(Integer, primary_key=True, autoincrement=True)
real_id = Column(Integer,ForeignKey('tbl_real.id'))
date_pub = Column(DATE,index=True)
date_prev = Column(DATE,index=True)
lon = Column(Integer,index=True)
lat = Column(Integer,index=True)
prec = Column(Integer,)
class Error(Base):
__tablename__ = 'tbl_error'
id = Column(Integer, primary_key=True)
forecast_id = Column(Integer,ForeignKey('tbl_forecast.id'))
real_id = Column(Integer,ForeignKey('tbl_realizado.id'))
error = Column(Integer)
Для вставки данных Error
я использую:
def insert_error_by_coord_data(self,real_id,lon,lat,date,prec,session):
ec_ext = session.query(Forecast.id,Forecast.prec).filter((Forecast.lon == lon)amp;
(Extendido.lat == lat)amp;
(Extendido.date_prev == date)).all()
data = list()
for row in ec_ext:
id = row[0]
if session.query(Erro).get(id) is None:
prev = comb[1]
error = prev - prec
data.append(Erro(id = id,
ext_id = id,
real_id = real_id,
error= error))
if len(data) > 0:
session.bulk_save_objects(objects=data)
session.commit()
session.close()
Каждый файл прогноза имеет 40 data_prev
и 25000 координат. И каждый реальный файл имеет 25000 координат. Прошло, я думаю, около 2 часов, а у меня всего 80000 строк Error
. Сначала на вставку записи уходило 1,03 секунды, а теперь это 3,04 секунды. Я использую 12 процессоров с multiprocessing
, если вы считаете, что здесь ошибка, пожалуйста, укажите, и я могу показать код, но я не думаю, что это так.
Вопрос в том, что я должен делать по-другому?
Комментарии:
1. lat, lng как целые числа??
2. Пожалуйста, предоставьте сгенерированный SQL —
SELECT ...
иCREATE TABLE ...
3. Когда я искал координату, я не нашел совпадений, и это было потому, что вместо 50,2 это было 50.200000005 (я на самом деле не помню, сколько нулей это было)
4.
DECIMAL
решает эту проблему. И дает вам больше точности. 1 градус широты составляет 69 миль (111 км).