forked from StellarSplit/StellarSplit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexplain-queries.ts
More file actions
103 lines (92 loc) · 3.45 KB
/
Copy pathexplain-queries.ts
File metadata and controls
103 lines (92 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { AppDataSource } from "../src/database/data-source";
async function run() {
await AppDataSource.initialize();
const ds = AppDataSource;
const userId = process.env.ANALYTICS_TEST_USER || null;
const dateFrom = process.env.ANALYTICS_TEST_FROM || null;
const dateTo = process.env.ANALYTICS_TEST_TO || null;
console.log("Running EXPLAIN ANALYZE for analytics queries");
// 1) Category breakdown base query (similar to getCategoryBreakdown)
// Build category query safely to avoid template quoting issues
let categorySql = `EXPLAIN ANALYZE
SELECT COALESCE(i.category, 'uncategorized') AS category, SUM(i."totalPrice"::numeric) AS amount
FROM items i
INNER JOIN splits sp ON i."splitId" = sp.id
INNER JOIN participants p ON p."splitId" = sp.id
WHERE 1=1`;
const categoryParams: any[] = [];
if (dateFrom) {
categorySql += `\nAND sp."createdAt" >= $${categoryParams.length + 1}`;
categoryParams.push(dateFrom);
}
if (dateTo) {
categorySql += `\nAND sp."createdAt" <= $${categoryParams.length + 1}`;
categoryParams.push(dateTo);
}
if (userId) {
categorySql += `\nAND p."userId" = $${categoryParams.length + 1}`;
categoryParams.push(userId);
}
categorySql += `\nGROUP BY category\nORDER BY amount DESC;`;
console.log("\n--- Category breakdown EXPLAIN ---");
try {
const res = await ds.query(categorySql, categoryParams);
console.log(res.map((r: any) => r["QUERY PLAN"] || r).join("\n"));
} catch (err) {
console.error("Category explain failed:", err);
}
// 2) Top partners query
const topPartnersSql = `EXPLAIN ANALYZE
SELECT p_other."userId" AS partnerId, SUM(payment.amount::numeric) as totalAmount, COUNT(*) as interactions
FROM participants p_self
INNER JOIN participants p_other ON p_self."splitId" = p_other."splitId"
INNER JOIN payments payment ON payment."participantId" = p_other.id
WHERE p_self."userId" = $1
AND p_other."userId" != $1
AND payment.status = 'confirmed'
GROUP BY partnerId
ORDER BY totalAmount DESC
LIMIT 10;`;
console.log("\n--- Top partners EXPLAIN ---");
if (!userId) {
console.log(
"Skipping top partners explain: set ANALYTICS_TEST_USER=<uuid> to run this check",
);
} else {
try {
const res = await ds.query(topPartnersSql, [userId]);
console.log(res.map((r: any) => r["QUERY PLAN"] || r).join("\n"));
} catch (err) {
console.error("Top partners explain failed:", err);
}
}
// 3) Materialized view usage (spending trends)
const trendsQuery = `EXPLAIN ANALYZE
SELECT * FROM analytics_spending_trends_monthly WHERE user_id = $1 ORDER BY period DESC LIMIT 24;`;
console.log("\n--- Spending trends (materialized view) EXPLAIN ---");
// Check if view exists first
try {
const exists = await ds.query(
`SELECT to_regclass('public.analytics_spending_trends_monthly') AS reg`,
);
if (!exists || !exists[0] || !exists[0].reg) {
console.log(
"Materialized view analytics_spending_trends_monthly not found; run migrations or create the view before running this check.",
);
} else {
try {
const res = await ds.query(trendsQuery, [userId || null]);
console.log(res.map((r: any) => r["QUERY PLAN"] || r).join("\n"));
} catch (err) {
console.error("Trends explain failed:", err);
}
}
} catch (err) {
console.error("Failed checking materialized view existence:", err);
}
await ds.destroy();
}
run().catch((err) => {
console.error(err);
process.exit(1);
});