Ich verwende den folgenden sqlalchemy Code einige Daten aus einer DatenbankLeistung SQLAlchemy und oder
q = session.query(hd_tbl).\
join(dt_tbl, hd_tbl.c['data_type'] == dt_tbl.c['ID']).\
filter(or_(and_(hd_tbl.c['object_id'] == get_id(row['object']),
hd_tbl.c['data_type'] == get_id(row['type']),
hd_tbl.c['data_provider'] == get_id(row['provider']),
hd_tbl.c['data_account'] == get_id(row['account']))
for index, row in data.iterrows())).\
with_entities(hd_tbl.c['ID'], hd_tbl.c['object_id'],
hd_tbl.c['data_type'], hd_tbl.c['data_provider'],
hd_tbl.c['data_account'], dt_tbl.c['value_type'])
wo hd_tbl
und dt_tbl
sind zwei Tabellen in SQL-Datenbank und data
ist Pandas Datenrahmen abzurufen typischerweise etwa 1k-9k Einträgen . hd_tbl
enthält im Moment rund 90k Zeilen.
Die Ausführungszeit scheint exponentiell mit der Länge von data
zu wachsen. Die entsprechende SQL-Anweisung (von sqlalchemy) sieht wie folgt aus:
SELECT data_header.`ID`, data_header.object_id, data_header.data_type, data_header.data_provider, data_header.data_account, basedata_data_type.value_type
FROM data_header INNER JOIN basedata_data_type ON data_header.data_type = basedata_data_type.`ID`
WHERE data_header.object_id = %s AND data_header.data_type = %s AND data_header.data_provider = %s AND data_header.data_account = %s OR
data_header.object_id = %s AND data_header.data_type = %s AND data_header.data_provider = %s AND data_header.data_account = %s OR
...
data_header.object_id = %s AND data_header.data_type = %s AND data_header.data_provider = %s AND data_header.data_account = %s OR
Die Tabellen und Spalten vollständig indiziert sind, und die Leistung ist nicht zufriedenstellend. Derzeit ist es viel schneller, alle Daten von hd_tbl
und dt_tbl
in den Speicher zu lesen und mit der Pandas-Merge-Funktion zusammenzuführen. Dies scheint jedoch suboptimal zu sein. Jemand, der eine Idee hat, wie man den Anruf von sqlalchemy verbessert?
EDIT: konnte ich Leistung signifcantly verbessern, indem sqlalchemy tuple_ auf folgende Weise mit:
header_tuples = [tuple([int(y) for y in tuple(x)]) for x in
data_as_int.values]
q = session.query(hd_tbl). \
join(dt_tbl, hd_tbl.c['data_type'] == dt_tbl.c['ID']). \
filter(tuple_(hd_tbl.c['object_id'], hd_tbl.c['data_type'],
hd_tbl.c['data_provider'],
hd_tbl.c['data_account']).in_(header_tuples)). \
with_entities(hd_tbl.c['ID'], hd_tbl.c['object_id'],
hd_tbl.c['data_type'], hd_tbl.c['data_provider'],
hd_tbl.c['data_account'], dt_tbl.c['value_type'])
mit entsprechender Abfrage ...
SELECT data_header.`ID`, data_header.object_id, data_header.data_type, data_header.data_provider, data_header.data_account, basedata_data_type.value_type
FROM data_header INNER JOIN basedata_data_type ON data_header.data_type = basedata_data_type.`ID`
WHERE (data_header.object_id, data_header.data_type, data_header.data_provider, data_header.data_account) IN ((%(param_1)s, %(param_2)s, %(param_3)s, %(param_4)s), (%(param_5)s, ...))
Nun, natürlich geht es langsam sein; Sie machen einen 'JOIN', indem Sie eine der Tabellen überschleifen und eine riesige' WHERE'-Klausel mit Tausenden von Bedingungen erstellen. Sie müssen eine temporäre Tabelle aus Ihrem Datenrahmen erstellen und eine ordnungsgemäße 'JOIN' durchführen. – univerio