perf(estimator): executemany batch insert in _save_yandex_history_items (Refs #826)
Replace N+1 loop `for row in rows: db.execute(sql, row)` with single `db.execute(sql, rows)` — SQLAlchemy Session passes list-of-dicts as executemany, reducing round-trips to one per batch. Guard with `if rows:` so empty batches skip the execute. Update unit tests to reflect one call with a list instead of N calls with individual dicts.
This commit is contained in:
parent
31d24ffbdb
commit
e4ad1f8f7a
2 changed files with 16 additions and 14 deletions
|
|
@ -659,8 +659,8 @@ def _save_yandex_history_items(
|
|||
)
|
||||
|
||||
try:
|
||||
for row in rows:
|
||||
db.execute(sql, row)
|
||||
if rows:
|
||||
db.execute(sql, rows)
|
||||
db.commit()
|
||||
return len(rows)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -84,10 +84,11 @@ def test_save_row_contains_house_id_and_confidence():
|
|||
):
|
||||
_save_yandex_history_items(db, result)
|
||||
|
||||
# db.execute called twice (one per item)
|
||||
assert db.execute.call_count == 2
|
||||
for c in db.execute.call_args_list:
|
||||
row = c.args[1]
|
||||
# db.execute called once with list-of-dicts (executemany, one round-trip)
|
||||
assert db.execute.call_count == 1
|
||||
rows = db.execute.call_args_list[0].args[1]
|
||||
assert isinstance(rows, list) and len(rows) == 2
|
||||
for row in rows:
|
||||
assert row["house_id"] == 54321
|
||||
assert row["confidence"] == pytest.approx(0.9)
|
||||
assert row["notes"] == "match_method=fingerprint"
|
||||
|
|
@ -117,8 +118,9 @@ def test_save_row_contains_removed_date():
|
|||
):
|
||||
_save_yandex_history_items(db, result)
|
||||
|
||||
row = db.execute.call_args_list[0].args[1]
|
||||
assert row["removed_date"] == date(2024, 5, 20)
|
||||
# args[1] is now the list-of-dicts passed to executemany
|
||||
rows = db.execute.call_args_list[0].args[1]
|
||||
assert rows[0]["removed_date"] == date(2024, 5, 20)
|
||||
|
||||
|
||||
def test_save_row_removed_date_none_when_active():
|
||||
|
|
@ -144,8 +146,8 @@ def test_save_row_removed_date_none_when_active():
|
|||
):
|
||||
_save_yandex_history_items(db, result)
|
||||
|
||||
row = db.execute.call_args_list[0].args[1]
|
||||
assert row["removed_date"] is None
|
||||
rows = db.execute.call_args_list[0].args[1]
|
||||
assert rows[0]["removed_date"] is None
|
||||
|
||||
|
||||
def test_save_handles_match_failure_gracefully():
|
||||
|
|
@ -172,10 +174,10 @@ def test_save_handles_match_failure_gracefully():
|
|||
saved = _save_yandex_history_items(db, result)
|
||||
|
||||
assert saved == 1
|
||||
row = db.execute.call_args_list[0].args[1]
|
||||
assert row["house_id"] is None
|
||||
assert row["confidence"] == pytest.approx(0.0)
|
||||
assert row["notes"] is None
|
||||
rows = db.execute.call_args_list[0].args[1]
|
||||
assert rows[0]["house_id"] is None
|
||||
assert rows[0]["confidence"] == pytest.approx(0.0)
|
||||
assert rows[0]["notes"] is None
|
||||
|
||||
|
||||
def test_save_match_called_with_address_and_year():
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue