Skip to content

Commit 76aa125

Browse files
committed
End perf currency rates
1 parent f1fb742 commit 76aa125

File tree

1 file changed

+69
-116
lines changed

1 file changed

+69
-116
lines changed

perf_currency_rate.py

Lines changed: 69 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,9 @@
55

66
from dateutil.relativedelta import relativedelta
77

8-
# from faker import Faker
9-
10-
# fake = Faker()
11-
12-
# faker -r=1000 -s=',' name email ean8 vat
138

149
currencies_ids = list(range(1, 8))
15-
company_ids = list(range(1, 10)) + ["NULL"]
10+
company_ids = list(range(1, 10)) + ['NULL']
1611
# +- 10 years of data
1712
days = [datetime.date.today()]
1813
for __ in range(10 * 365):
@@ -25,11 +20,31 @@
2520
line = ",".join([str(currency_id), str(date), str(company_id), str(rate)])
2621
f.write(f"{line}\n")
2722

28-
""" CREATE UNIQUE INDEX test_cur ON res_currency_rate (currency_id, company_id, name DESC) NULLS NOT DISTINCT """
23+
# Before indexes:
24+
"""
25+
CREATE UNIQUE INDEX res_currency_rate_unique_name_per_day ON res_currency_rate (name, currency_id, company_id);
26+
-- OR
27+
CREATE UNIQUE INDEX res_currency_rate_unique_name_per_day ON res_currency_rate (name, currency_id, company_id) NULLS NOT DISTINCT;
28+
"""
2929

30+
# Now indexes:
31+
"""
32+
CREATE UNIQUE INDEX res_currency_rate_reversed_unique_name_per_day ON res_currency_rate (currency_id, company_id, name DESC) NULLS NOT DISTINCT;
33+
CREATE UNIQUE INDEX res_currency_rate_unique_name_per_day ON res_currency_rate (currency_id, company_id, name) NULLS NOT DISTINCT;
34+
"""
3035

31-
# Current solution without gettind date of rate
36+
# Before queries
3237
"""
38+
SELECT DISTINCT ON ("res_currency_rate"."currency_id")
39+
"res_currency_rate"."currency_id", "res_currency_rate"."rate"
40+
FROM "res_currency_rate"
41+
WHERE ("res_currency_rate"."company_id" IS NULL OR "res_currency_rate"."company_id" = 1)
42+
ORDER BY
43+
"res_currency_rate"."currency_id",
44+
"res_currency_rate"."company_id",
45+
CASE WHEN "res_currency_rate"."name" <= '2025-09-02'::date THEN "res_currency_rate"."name" END DESC,
46+
CASE WHEN "res_currency_rate"."name" > '2025-09-02'::date THEN "res_currency_rate"."name" END ASC;
47+
3348
SELECT
3449
"res_currency"."id",
3550
COALESCE(
@@ -66,115 +81,53 @@
6681
), 1.0
6782
)
6883
FROM
69-
"res_currency"
70-
WHERE "res_currency"."id" IN %s
71-
"""
72-
73-
""" 10 currencies
74-
Index Only Scan using res_currency_pkey on res_currency (cost=0.14..24132.82 rows=7 width=36) (actual time=7.065..19.959 rows=7 loops=1)
75-
Index Cond: (id = ANY ('{4,5,3,2,6,8,1}'::integer[]))
76-
Heap Fetches: 7
77-
SubPlan 1
78-
-> Limit (cost=1768.76..1768.76 rows=1 width=20) (actual time=2.845..2.845 rows=1 loops=7)
79-
-> Sort (cost=1768.76..1772.05 rows=1317 width=20) (actual time=2.844..2.844 rows=1 loops=7)
80-
Sort Key: res_currency_rate.company_id, res_currency_rate.name DESC
81-
Sort Method: quicksort Memory: 25kB
82-
-> Index Scan using res_currency_rate__currency_id_index on res_currency_rate (cost=0.42..1762.17 rows=1317 width=20) (actual time=0.005..2.221 rows=6259 loops=7)
83-
Index Cond: (currency_id = res_currency.id)
84-
Filter: (((company_id = 1) OR (company_id IS NULL)) AND (name <= '2025-10-06'::date) AND ((company_id = 1) OR (company_id IS NULL)))
85-
Rows Removed by Filter: 25035
86-
SubPlan 2
87-
-> Limit (cost=1677.48..1677.48 rows=1 width=20) (actual time=0.003..0.003 rows=0 loops=1)
88-
-> Sort (cost=1677.48..1680.77 rows=1317 width=20) (actual time=0.003..0.003 rows=0 loops=1)
89-
Sort Key: res_currency_rate_1.company_id, res_currency_rate_1.name
90-
Sort Method: quicksort Memory: 25kB
91-
-> Index Scan using res_currency_rate__currency_id_index on res_currency_rate res_currency_rate_1 (cost=0.42..1670.89 rows=1317 width=20) (actual time=0.001..0.001 rows=0 loops=1)
92-
Index Cond: (currency_id = res_currency.id)
93-
Filter: (((company_id = 1) OR (company_id IS NULL)) AND ((company_id = 1) OR (company_id IS NULL)))
94-
Planning Time: 0.418 ms
95-
Execution Time: 20.002 ms
96-
(22 rows)
97-
"""
98-
99-
""" 2 currencies
100-
Index Only Scan using res_currency_pkey on res_currency (cost=0.14..6900.81 rows=2 width=36) (actual time=7.319..9.923 rows=2 loops=1)
101-
Index Cond: (id = ANY ('{4,1}'::integer[]))
102-
Heap Fetches: 2
103-
SubPlan 1
104-
-> Limit (cost=1768.76..1768.76 rows=1 width=20) (actual time=4.946..4.947 rows=1 loops=2)
105-
-> Sort (cost=1768.76..1772.05 rows=1317 width=20) (actual time=4.945..4.945 rows=1 loops=2)
106-
Sort Key: res_currency_rate.company_id, res_currency_rate.name DESC
107-
Sort Method: top-N heapsort Memory: 25kB
108-
-> Index Scan using res_currency_rate__currency_id_index on res_currency_rate (cost=0.42..1762.17 rows=1317 width=20) (actual time=0.012..3.825 rows=7302 loops=2)
109-
Index Cond: (currency_id = res_currency.id)
110-
Filter: (((company_id = 1) OR (company_id IS NULL)) AND (name <= '2025-10-06'::date) AND ((company_id = 1) OR (company_id IS NULL)))
111-
Rows Removed by Filter: 29208
112-
SubPlan 2
113-
-> Limit (cost=1677.48..1677.48 rows=1 width=20) (never executed)
114-
-> Sort (cost=1677.48..1680.77 rows=1317 width=20) (never executed)
115-
Sort Key: res_currency_rate_1.company_id, res_currency_rate_1.name
116-
-> Index Scan using res_currency_rate__currency_id_index on res_currency_rate res_currency_rate_1 (cost=0.42..1670.89 rows=1317 width=20) (never executed)
117-
Index Cond: (currency_id = res_currency.id)
118-
Filter: (((company_id = 1) OR (company_id IS NULL)) AND ((company_id = 1) OR (company_id IS NULL)))
119-
Planning Time: 0.427 ms
120-
Execution Time: 9.969 ms
121-
(21 rows)
84+
"res_currency";
12285
"""
12386

124-
# Solution use for left join
87+
# New solution
12588
"""
126-
SELECT DISTINCT ON ("res_currency_rate"."currency_id")
127-
"res_currency_rate"."currency_id", "res_currency_rate"."rate"
128-
FROM "res_currency_rate"
129-
WHERE ("res_currency_rate"."company_id" IS NULL OR "res_currency_rate"."company_id" = 1)
130-
AND "res_currency_rate"."currency_id" IN %s
131-
ORDER BY
132-
"res_currency_rate"."currency_id",
133-
"res_currency_rate"."company_id",
134-
CASE WHEN "res_currency_rate"."name" <= '2025-09-02'::date THEN "res_currency_rate"."name" END DESC,
135-
CASE WHEN "res_currency_rate"."name" > '2025-09-02'::date THEN "res_currency_rate"."name" END ASC
136-
"""
137-
138-
"""
139-
Unique (cost=1697.99..12509.19 rows=7 width=28) (actual time=7.591..25.273 rows=6 loops=1)
140-
-> Incremental Sort (cost=1697.99..12404.92 rows=41710 width=28) (actual time=7.590..24.304 rows=43812 loops=1)
141-
Sort Key: currency_id, company_id, (CASE WHEN (name <= '2025-09-02'::date) THEN name ELSE NULL::date END) DESC, (CASE WHEN (name > '2025-09-02'::date) THEN name ELSE NULL::date END)
142-
Presorted Key: currency_id
143-
Full-sort Groups: 6 Sort Method: quicksort Average Memory: 28kB Peak Memory: 28kB
144-
Pre-sorted Groups: 6 Sort Method: quicksort Average Memory: 561kB Peak Memory: 561kB
145-
-> Index Scan using res_currency_rate__currency_id_index on res_currency_rate (cost=0.42..9268.03 rows=41710 width=28) (actual time=0.040..14.706 rows=43812 loops=1)
146-
Index Cond: (currency_id = ANY ('{4,5,3,2,6,8,1}'::integer[]))
147-
Filter: ((company_id IS NULL) OR (company_id = 1))
148-
Rows Removed by Filter: 175248
149-
Planning Time: 0.218 ms
150-
Execution Time: 25.322 ms
151-
"""
152-
153-
"""
154-
Unique (cost=558.49..4113.84 rows=7 width=28) (actual time=14.670..23.277 rows=2 loops=1)
155-
-> Incremental Sort (cost=558.49..4079.37 rows=13786 width=28) (actual time=14.668..22.420 rows=14604 loops=1)
156-
Sort Key: currency_id, company_id, (CASE WHEN (name <= '2025-09-02'::date) THEN name ELSE NULL::date END) DESC, (CASE WHEN (name > '2025-09-02'::date) THEN name ELSE NULL::date END)
157-
Presorted Key: currency_id
158-
Full-sort Groups: 2 Sort Method: quicksort Average Memory: 28kB Peak Memory: 28kB
159-
Pre-sorted Groups: 2 Sort Method: quicksort Average Memory: 561kB Peak Memory: 561kB
160-
-> Index Scan using res_currency_rate__currency_id_index on res_currency_rate (cost=0.42..3152.57 rows=13786 width=28) (actual time=0.038..13.422 rows=14604 loops=1)
161-
Index Cond: (currency_id = ANY ('{4,1}'::integer[]))
162-
Filter: ((company_id IS NULL) OR (company_id = 1))
163-
Rows Removed by Filter: 58416
164-
Planning Time: 0.237 ms
165-
Execution Time: 23.334 ms
166-
"""
167-
168-
"""
169-
SELECT DISTINCT ON ("res_currency_rate"."currency_id")
170-
"res_currency_rate"."currency_id", "res_currency_rate"."rate"
171-
FROM "res_currency_rate"
172-
WHERE ("res_currency_rate"."company_id" IS NULL OR "res_currency_rate"."company_id" = 1)
173-
AND "res_currency_rate"."currency_id" IN %s
174-
ORDER BY
175-
"res_currency_rate"."currency_id",
176-
"res_currency_rate"."company_id",
177-
"res_currency_rate"."name" DESC;
89+
EXPLAIN ANALYSE SELECT
90+
"res_currency"."id",
91+
COALESCE("before_rate"."rate", "after_rate"."rate", 1.0) AS "rate",
92+
COALESCE("before_rate"."name", "after_rate"."name") AS "name"
93+
FROM
94+
"res_currency"
95+
LEFT JOIN LATERAL (
96+
SELECT
97+
"rate",
98+
"name"
99+
FROM
100+
"res_currency_rate"
101+
WHERE
102+
(
103+
(
104+
"res_currency_rate"."company_id" IN (1)
105+
OR "res_currency_rate"."company_id" IS NULL
106+
)
107+
AND "res_currency_rate"."name" <= '2025-10-09'
108+
)
109+
AND "res_currency_rate"."currency_id" = "res_currency"."id"
110+
ORDER BY
111+
"res_currency_rate"."company_id",
112+
"res_currency_rate"."name" DESC
113+
LIMIT
114+
1
115+
) AS "before_rate" ON (TRUE)
116+
LEFT JOIN LATERAL (
117+
SELECT
118+
"rate",
119+
"name"
120+
FROM
121+
"res_currency_rate"
122+
WHERE
123+
(
124+
"res_currency_rate"."company_id" IN (1)
125+
OR "res_currency_rate"."company_id" IS NULL
126+
)
127+
AND "res_currency_rate"."currency_id" = "res_currency"."id"
128+
ORDER BY
129+
"res_currency_rate"."company_id",
130+
"res_currency_rate"."name" ASC
131+
LIMIT 1
132+
) AS "after_rate" ON ("before_rate"."rate" IS NULL);
178133
"""
179-
180-

0 commit comments

Comments
 (0)