github.com/square/finch@v0.0.0-20240412205204-6530c03e2b96/docs/content/syntax/trx-file.md (about) 1 --- 2 weight: 2 3 --- 4 5 Trx files are plain text format with blank lines separating SQL statements. 6 7 {{< hint type=tip >}} 8 Use a `.sql` file extension to enable SQL syntax highlighting in your editor. 9 {{< /hint >}} 10 11 {{< toc >}} 12 13 ## Format 14 15 * Statements must be separated by one or more blank lines (example 1) 16 * A single statement can span multiple lines as long as none of them are blank (example 2) 17 * Statement modifiers are single-line SQL comments immediately preceding the statement (example 3) 18 * SQL substitutions are one line `/*! ... */` SQL comments embedded in the statement (example 4) 19 20 {{< columns >}} 21 _Example 1_ 22 ```sql 23 SELECT q FROM t WHERE id = @d 24 25 DELETE FROM t WHERE id = @d 26 ``` 27 <---> 28 _Example 2_ 29 ```sql 30 INSERT INTO t 31 (q, r, s) 32 VALUES 33 , (@q, 2, 3) 34 , (@q, 5, 6) 35 ``` 36 {{< /columns >}} 37 38 {{< columns >}} 39 _Example 3_ 40 ```sql 41 BEGIN 42 43 -- save-result: @q, _ 44 SELECT q, r FROM t WHERE id = @d 45 46 DELETE FROM t WHERE q = @q 47 48 COMMIT 49 ``` 50 <---> 51 _Example 4_ 52 ```sql 53 -- prepare 54 -- rows: ${params.rows} 55 INSERT INTO t VALUES /*!csv 100 (NULL, @d)*/ 56 ``` 57 {{< /columns >}} 58 59 ## Statement Modifiers 60 61 Statement modifiers modify how Finch executes and handles a statement. 62 They are all optional, but most benchmarks use a few of them, especially during a setup stage. 63 64 ### copies 65 66 `-- copies: N` 67 68 Add N-1 copies to output 69 {.tagline} 70 71 {{< columns >}} 72 _Input_ → 73 ```sql 74 -- copies: 3 75 SELECT foo 76 ``` 77 <---> 78 _Output_ 79 ```sql 80 SELECT foo 81 82 SELECT foo 83 84 SELECT foo 85 ``` 86 {{< /columns >}} 87 88 `N` is the _total_ number of statements in the output: 89 90 |N|Output| 91 |-|------| 92 |< 0|(Error)| 93 |1|No change; first statement| 94 |≥ 2|First statement plus N-1 more| 95 {.compact .params} 96 97 If you want 10 copies of the same statement, you can write the statement (and its SQL modifiers) 10 times. 98 Or you can write it once, add `-- copies: 10`, and Finch will automatically write the other 9 copies. 99 100 The copies are identical as if you had written all N of them. 101 The only difference is when this modifier is combined with [`prepare`](#prepare): prepare on copies make a single prepared statement for all copies. 102 103 ### database-size 104 105 `-- database-size: DB SIZE` 106 107 Insert rows until database reaches a certain size 108 109 |Variable|Value| 110 |--------|-----| 111 |`DB`|Unquoted database name to check| 112 |`SIZE`|[string-int]({{< relref "syntax/values#string-int" >}}) > 0 (examples: 100MB, 5.1GB, 2TB)| 113 114 After the table size is reached, the client stops even if other [limits]({{< relref "data/limits" >}}) have not been reached. 115 116 The size is not exact because it's checked periodically. 117 The final size is usually a little larger, but not by much. 118 119 ### idle 120 121 `-- idle: TIME` 122 123 Sleep for some time 124 {.tagline} 125 126 `TIME` is a [time duration]({{< relref "syntax/values#time-duration" >}}), like "5ms" for 5 millisecond. 127 128 This is useful to simulate known delays, stalls, or latencies in application code. 129 It's also useful to benchmark the effects of migrating to a slower environment, like migrating MySQL from bare metal with local storage to the cloud with network storage. 130 131 An idle sleep does _not_ count as a query, and it's not directly measured or reported in [statistics]({{< relref "benchmark/statistics" >}}). 132 133 ### prepare 134 135 `-- prepare` 136 137 Use a prepared statement to execute the query 138 {.tagline} 139 140 By default, Finch does not use prepared statements: data keys (@d) are replaced with generated values, and the whole SQL statement string is sent to MySQL. 141 But with `-- prepare`, data keys become SQL parameters (?), Finch prepares the SQL statement, and uses generated values for the SQL parameters. 142 143 ### rows 144 145 `-- rows: N` 146 147 Insert N many rows 148 {.tagline} 149 150 After N rows, the client stops even if other [limits]({{< relref "data/limits" >}}) have not been reached. 151 152 ### save-columns 153 154 `-- save-columns: @d, _` 155 156 Save columns into corresponding data keys, or "_" to ignore 157 {.tagline} 158 159 For SELECT statements, the built-in [column data generator]({{< relref "data/generators#column" >}}) can save column values from the _last row_ of the result set. 160 Every column must have a corresponding data key or "\_" to ignore the column: 161 162 ```sql 163 -- save-columns: @d, _, @q 164 SELECT a, b, c FROM t WHERE ... 165 ``` 166 167 The example above saves `a` → @d, ignores `b`, and `c` → @q—from the _last row_ of the result set. 168 (@d and @q must be defined in the stage file and use the column generator, but "\_" is not defined anywhere.) 169 Since the column data generator defaults to [trx data scope]({{< relref "data/scope#trx" >}}), you can use @d and @q in another statement in the same trx. 170 171 {{< hint type=note >}} 172 The default [data scope]({{< relref "data/scope" >}}) for column data is _trx_, not statement. 173 {{< /hint >}} 174 175 By default, only column values from the last row of the result set are changed, but all rows are scanned. 176 Therefore, you can implement a [custom data generator]({{< relref "api/data" >}}) to save the entire result set. 177 178 ### save-insert-id 179 180 `-- save-insert-id: @d` 181 182 Save insert ID as @d 183 {.tagline} 184 185 This only works for a single row INSERT, and @d must be configured to use the [column data generator]({{< relref "data/generators#column" >}}). 186 187 As a silly example, this trx inserts a row then deletes it: 188 189 ```sql 190 -- save-insert-id: @d 191 INSERT INTO t VALUES (...) 192 193 DELETE FROM t WHERE id = @d 194 ``` 195 196 ### table-size 197 198 `-- table-size: TABLE SIZE` 199 200 Insert rows until table reaches a certain size 201 {.tagline} 202 203 |Variable|Value| 204 |--------|-----| 205 |`TABLE`|Unquoted table name to check (can be database-qualified)| 206 |`SIZE`|[string-int]({{< relref "syntax/values#string-int" >}}) > 0 (examples: 100MB, 5.1GB, 2TB)| 207 208 After the table size is reached, the client stops even if other [limits]({{< relref "data/limits" >}}) have not been reached. 209 210 The size is not exact because it's checked periodically. 211 The final size is usually a little larger, but not by much. 212 213 ## SQL Substitutions 214 215 SQL substitutions change parts of the SQL statement. 216 217 ### copy-number 218 219 `/*!copy-number*/` 220 221 Replaced by the [copy number](#copies). 222 223 This can be used anywhere, including a table definition like: 224 225 {{< columns >}} 226 _Input_ → 227 ```sql 228 -- copies: 2 229 CREATE TABLE t/*!copy-number*/ ( 230 ... 231 ) 232 ``` 233 <---> 234 _Output_ 235 ```sql 236 CREATE TABLE t1 ( 237 ... 238 ) 239 240 CREATE TABLE t2 ( 241 ... 242 ) 243 ``` 244 {{< /columns >}} 245 246 ### csv 247 248 `/*!csv N (COLS)*/` 249 250 Writes `N` many `(COLS)`, comma-separated, to generate multi-row INSERT statements. 251 252 {{< columns >}} 253 _Input_ → 254 ```sql 255 INSERT INTO t VALUES /*!csv 3 (a, @d)*/ 256 ``` 257 <---> 258 _Output_ 259 ```sql 260 INSERT INTO t VALUES (a, @d), (a, @d), (a, @d) 261 ``` 262 {{< /columns >}} 263 264 265 By default, Finch uses [row scope]({{< relref "data/scope#row" >}}) for all data keys in a CSV substitution. 266 This is usually correct, but you can override by configuring an explicit data scope—but doing so might produce duplicate values/rows. 267 268 Finch does not auto-detect manually written multi-row INSERT statements. 269 For these, you probably want [statement scope]({{< relref "data/scope#statement" >}}) plus [explicit calls]({{< relref "data/scope#explicit-call" >}}). 270 271 {{< hint type=tip >}} 272 The fastest way to bulk-insert rows is by combining CSV substitution, [prepare](#prepare), and multiple clients. 273 `N = 1000` or more is possible; the limiting factor is MySQL system variable [`max_allowed_packet`](https://dev.mysql.com/doc/refman/en/server-system-variables.html#sysvar_max_allowed_packet). 274 {{< /hint >}}