split paginated trades query in 2 - #4954
Conversation
|
Claude finished @MartinquaXD's task in 4m 25s —— View job PR Review: split paginated trades query in 2I reviewed the SQL rewrite and the orderbook wiring. Overall this is a clean, well-documented change and the semantics of the old unified query are faithfully preserved:
I left two non-blocking inline comments:
Note: I couldn't run |
|
Claude finished @MartinquaXD's task in 2m 52s —— View job PR Review: split paginated trades query in 2Nice change — splitting the unified query into I left one inline finding:
The two points from the earlier automated review still stand and I won't restate them: the likely-redundant Note: I couldn't run |
|
Reminder: Please update the DB Readme and comment whether migrations are reversible (include rollback scripts if applicable).
Caused by: |
AryanGodara
left a comment
There was a problem hiding this comment.
left a few comments. Looks good overall 👌🏼
There was a problem hiding this comment.
overall LGTM
One (non-blocking) nit: the new jit test doesn't actually guard the branch-3 DISTINCT (I removed it and the test stayed green, the page-level DISTINCT masks it at limit 1000). Left a small-limit test on the thread that fails without the fix.
Description
The /trades endpoint allows to pass 2 different filters (by order_uid and by owner). Those are currently mutually exclusive but are handled by the same underlying postgres query. That means the query has to be generic enough to serve both use cases which prevents some optimizations and makes the query quite complicated to achieve reasonable performance.
Changes
Model the query filter as an enum and split the postgres query into 2 dedicated queries. Especially the pathological case that gets triggered a lot recently (one order with MANY partial fills) can be optimized more with a dedicated query.
Also added a new index which also turns the last sub-query of the owner based query into an index only scan.
The index was already created on all the prod DBs (they were super fast to create anyway) so I decided to not use
CONCURRENTLYwhen creating the index. That way was can create the new index and drop the old one in a single transaction.How to test
existing postgres tests still pass
Synthetic benchmark on cached queries
Test on prod. I created a scrip that exercised the same pathological behavior as the recent BNB spammer (1 order with thousands of trades with a huge offset and limit). The first diagram shows the number of problematic requests that were handled by the system. And the second diagram shows how much the DB was stressed during the time.
I wrote a small script to spam our orderbook myself and as we can see despite sending roughly twice the number of requests as the real spammer the DB was under significantly less load with the 2 specialized queries.