Commit 1fc9168
committed
Make our query builder faster than a SQL string (diesel-rs#283)
We've added a new trait, `QueryId`, which must be implemented for all
AST nodes, and optionally returns a type which conforms to
`std::any::Any`. Nodes which have their SQL change without the type
changing (such as boxed nodes) will return `None` here. If we're able to
uniquely identify the query on the type alone, we use that for the cache
key rather than the SQL string. This allows us to skip the query
construction entirely. Additionally, a type identifier can be used for a
faster hash lookup than a string could, allowing us to actually beat the
string literal case.
My intent is that all types which implement `QueryFragment` also
implement `QueryId`. However, we can't make it a supertrait, as that
would require specifying the `QueryId` associated type when creating a
boxed trait object, which defeats the purpose entirely. Ironcially, we
actually implement `QueryId` for the trait object directly, so in theory
we should be able to separate them. I don't know if there's a way to
actually do this, though.
There's a handful of types which implement the "noop" form of `TypeId`
that could potentially be safe to implement for real. The main one that
comes to mind is `Aliased`. While the SQL from its implementation of
`QueryFragment` implies that the SQL can change without the type, I
think the type encapsulates enough information. It's a niche feature
though so I erred on the side of caution.
Here are the benchmark results:
```
name old ns/iter new ns/iter diff ns/iter diff %
pg::connection::tests::benchmarks::prepared_statement_lookup_query_builder 1,048 191 -857 -81.77%
pg::connection::tests::benchmarks::prepared_statement_lookup_raw_sql 319 318 -1 -0.31%
sqlite::connection::tests::benchmarks::prepared_statement_lookup_query_builder 743 123 -620 -83.45%
sqlite::connection::tests::benchmarks::prepared_statement_lookup_raw_sql 183 180 -3 -1.64%
```
These benchmarks measured creating/fetch the prepared statement, without
executing the query (calling `prepare_query` on both backends). I opted
to benchmark this as the inherent noise of a database round trip on PG
made it difficult to demonstrate the difference. The benchmarks are not
included in this PR as the code is messy and these aren't benchmarks
that I care to keep in the long term.
We could potentially gain a little bit more performance here. A type
identifier is a u64 internally, so can be used with a perfect hashing
function. This would change the lookup to be constant time. I believe
this could save us another 100 ns or so, bringing the query builder
close to 0.1 parent 2125aaf commit 1fc9168
43 files changed
Lines changed: 473 additions & 60 deletions
File tree
- diesel_tests/tests
- schema_dsl
- diesel/src
- connection
- expression
- functions
- ops
- pg
- connection
- stmt
- expression
- types
- query_builder
- select_statement
- update_statement
- query_dsl
- query_source
- sqlite/connection
- types/impls
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
69 | 69 | | |
70 | 70 | | |
71 | 71 | | |
72 | | - | |
| 72 | + | |
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
| 89 | + | |
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
48 | 56 | | |
49 | 57 | | |
50 | 58 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| 65 | + | |
| 66 | + | |
65 | 67 | | |
66 | 68 | | |
67 | 69 | | |
| |||
132 | 134 | | |
133 | 135 | | |
134 | 136 | | |
| 137 | + | |
| 138 | + | |
135 | 139 | | |
136 | 140 | | |
137 | 141 | | |
| |||
163 | 167 | | |
164 | 168 | | |
165 | 169 | | |
| 170 | + | |
| 171 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
58 | 66 | | |
59 | 67 | | |
60 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| 77 | + | |
| 78 | + | |
77 | 79 | | |
78 | 80 | | |
79 | 81 | | |
| |||
102 | 104 | | |
103 | 105 | | |
104 | 106 | | |
| 107 | + | |
| 108 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
| 53 | + | |
52 | 54 | | |
53 | 55 | | |
54 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
49 | 51 | | |
50 | 52 | | |
51 | 53 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
| 62 | + | |
61 | 63 | | |
62 | 64 | | |
63 | 65 | | |
| |||
134 | 136 | | |
135 | 137 | | |
136 | 138 | | |
| 139 | + | |
| 140 | + | |
137 | 141 | | |
138 | 142 | | |
139 | 143 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
32 | 34 | | |
| |||
0 commit comments