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_ &rarr;
    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  |&lt; 0|(Error)|
    93  |1|No change; first statement|
    94  |&ge; 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" >}}) &gt; 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` &rarr; @d, ignores `b`, and `c` &rarr; @q&mdash;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" >}}) &gt; 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_ &rarr;
   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_ &rarr;
   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&mdash;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 >}}