perf(spend_tracking): index LiteLLM_SpendLogs by (api_key, startTime)

Every per-key spend read filters WHERE api_key = ... AND startTime in a
range (/spend/logs?api_key=..., the key-filtered UI logs page, external
billing readers), but LiteLLM_SpendLogs carries no api_key index, so each
such query scans every logged request on the instance. Composite with
startTime to match the query shape, mirroring the existing
(startTime, request_id) composite.

Measured on Postgres 18 with 1.6M spend rows: one key's 7-day SUM goes
from a 93.9ms parallel seq scan to a 0.7ms bitmap index scan (~140x);
a batch job reading per-key spend for 10k keys went from 20.5s to 1.7s.
This commit is contained in:
Etienne Chabert 2026-08-23 01:44:49 +02:00
parent aae36f4bd4
commit 555d5d507b
No known key found for this signature in database
4 changed files with 5 additions and 0 deletions

View file

@ -0,0 +1,2 @@
-- CreateIndex
CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_api_key_startTime_idx" ON "LiteLLM_SpendLogs"("api_key", "startTime");

View file

@ -647,6 +647,7 @@ model LiteLLM_SpendLogs {
@@index([startTime, request_id])
@@index([end_user])
@@index([session_id])
@@index([api_key, startTime])
}
// View spend, model, api_key per request

View file

@ -647,6 +647,7 @@ model LiteLLM_SpendLogs {
@@index([startTime, request_id])
@@index([end_user])
@@index([session_id])
@@index([api_key, startTime])
}
// View spend, model, api_key per request

View file

@ -647,6 +647,7 @@ model LiteLLM_SpendLogs {
@@index([startTime, request_id])
@@index([end_user])
@@index([session_id])
@@index([api_key, startTime])
}
// View spend, model, api_key per request