|
1 | | -# Query Rewrites Reference — DSQL-Specific |
| 1 | +# Query Rewrites — DSQL-Specific |
2 | 2 |
|
3 | | -SQL rewrites that address Aurora DSQL-specific behaviors and limitations. Apply these when the plan reveals inefficiency unique to DSQL's distributed architecture or optimizer constraints. |
| 3 | +SQL rewrites that address Aurora DSQL-specific behaviors and optimizer constraints. These SHOULD be recommended when the plan reveals inefficiency unique to DSQL's distributed architecture. |
4 | 4 |
|
5 | | -## Table of Contents |
| 5 | +## Available Rewrites |
6 | 6 |
|
7 | | -1. [Replace COUNT(*) with reltuples Estimate](#replace-count-with-reltuples-estimate) |
8 | | -2. [Split Large Joins to Enable Optimal Join Ordering](#split-large-joins-to-enable-optimal-join-ordering) |
9 | | - |
10 | | ---- |
11 | | - |
12 | | -## Replace COUNT(*) with reltuples Estimate |
13 | | - |
14 | | -When a query performs `COUNT(*)` on a large table, rewrite to use the `reltuples` value from `pg_class` for an approximate row count. This is a common workaround for cases where `COUNT(*)` is too slow or times out on large tables. |
15 | | - |
16 | | -**When to apply:** An approximate count is acceptable and the table is large enough that `COUNT(*)` is prohibitively expensive. |
17 | | - |
18 | | -**Do not apply:** The application requires an exact count. |
19 | | - |
20 | | -```sql |
21 | | --- Original |
22 | | -SELECT COUNT(*) AS exact_count |
23 | | -FROM big_table; |
24 | | - |
25 | | --- Rewritten (DSQL) |
26 | | -SELECT reltuples::bigint AS estimated_count |
27 | | -FROM pg_class |
28 | | -WHERE oid = 'public.big_table'::regclass; |
29 | | -``` |
30 | | - |
31 | | -```sql |
32 | | --- Not applicable: exact count required |
33 | | -SELECT COUNT(*) AS exact_count |
34 | | -FROM big_table; |
35 | | -``` |
36 | | - |
37 | | ---- |
38 | | - |
39 | | -## Split Large Joins to Enable Optimal Join Ordering |
40 | | - |
41 | | -If a query joins more tables than the optimizer's DP threshold (e.g., 10 joins for Aurora DSQL), rewrite it into multiple subqueries each joining no more tables than the threshold, then join the subquery results. |
42 | | - |
43 | | -This allows the PostgreSQL-based DSQL engine to apply dynamic-programming (DP) join ordering within each smaller block, producing a better overall join plan than a greedy algorithm on many tables. |
44 | | - |
45 | | -**When to apply:** The total number of joined tables exceeds the DP threshold (`join_collapse_limit` or `from_collapse_limit`). Partition the join into CTEs each with table count at or below the threshold, push down relevant filters, and join the CTE results. |
46 | | - |
47 | | -**Do not apply:** The total table count is at or below the threshold, or splitting would prevent necessary cross-block optimizations. |
48 | | - |
49 | | -```sql |
50 | | --- Original |
51 | | -SELECT * |
52 | | -FROM R1 |
53 | | - JOIN R2 ON R1.id = R2.id |
54 | | - JOIN R3 ON R2.id = R3.id |
55 | | - JOIN R4 ON R3.id = R4.id |
56 | | - JOIN R5 ON R4.id = R5.id |
57 | | - JOIN R6 ON R5.id = R6.id |
58 | | - JOIN R7 ON R6.id = R7.id |
59 | | -WHERE Filters; |
60 | | - |
61 | | --- Rewritten (DSQL) |
62 | | -WITH |
63 | | - sub1 AS ( |
64 | | - SELECT * |
65 | | - FROM R1 |
66 | | - JOIN R2 ON R1.id = R2.id |
67 | | - JOIN R3 ON R2.id = R3.id |
68 | | - JOIN R4 ON R3.id = R4.id |
69 | | - WHERE <Filter 1> |
70 | | - ), |
71 | | - sub2 AS ( |
72 | | - SELECT * |
73 | | - FROM R5 |
74 | | - JOIN R6 ON R5.id = R6.id |
75 | | - JOIN R7 ON R6.id = R7.id |
76 | | - WHERE <Filter 2> |
77 | | - ) |
78 | | -SELECT * |
79 | | -FROM sub1 |
80 | | -JOIN sub2 ON sub1.id = sub2.id; |
81 | | -``` |
82 | | - |
83 | | -```sql |
84 | | --- Not applicable: total tables ≤ DP threshold |
85 | | -SELECT * |
86 | | -FROM R1 |
87 | | - JOIN R2 ON R1.id = R2.id |
88 | | - JOIN R3 ON R2.id = R3.id |
89 | | - JOIN R4 ON R3.id = R4.id |
90 | | -WHERE Filters; |
91 | | -``` |
| 7 | +| Pattern Detected | Reference File | |
| 8 | +| ------------------------------- | ------------------------------------------------------------- | |
| 9 | +| COUNT(*) timeout on large table | [reltuples-estimate.md](query-rewrites/reltuples-estimate.md) | |
| 10 | +| Join count exceeds DP threshold | [split-large-joins.md](query-rewrites/split-large-joins.md) | |
0 commit comments