SQL Server
Benchmarks
How ARX compares with other ways of doing the same work on SQL Server, measured with BenchmarkDotNet.
A living summary of the SQL Server benchmarks: how ARX compares with raw Microsoft.Data.SqlClient, Dapper and EF Core. Update it whenever a benchmark is rerun or an operation is added.
| Last updated | 2026-11-09: first full run of every operation (108 benchmarks), then Delete rerun after the JSON-list change |
| Operations measured | Create, CreateMultiple, Update, UpdateMultiple, Delete, DeleteMultiple, Retrieve, RetrieveMultiple (rows, a page with the total), Execute (a procedure with result rows and OUTPUT values, a scalar function) |
| Machine | Intel Core i7-8750H, Windows 11, .NET 10.0.14, SQL Server 2022 (16.0.4225.2, mcr.microsoft.com/mssql/server:2022-latest) in Docker Desktop, Microsoft.Data.SqlClient 7.1.1, BenchmarkDotNet 0.15.8, job Standard (8 iterations, 3 warm-ups) |
| Compared with | Raw SqlClient (hand-written, typed parameters), Dapper 2.1.89, EF Core 10 (Microsoft.EntityFrameworkCore.SqlServer 10.0.0), SqlBulkCopy |
| Reports | The full run: results/2026-11-09-full-run/. Delete after the change: results/2026-11-09-delete-after-json-list.md. The IN-list probe: results/probes/in-list-vs-openjson.md. After READ COMMITTED on writes (E16): Update, Delete (ARX and raw only). |
In one line: ARX is level with hand-written SqlClient for single-row work, level with the best hand-written form for many-row writes (and far ahead of the usual one and of EF Core), level with Dapper and EF Core for reads, and ahead of everyone for deleting lists of 100 to 1,000 ids. Raw typed readers are faster than ARX's dictionaries for large reads.
Read the ratios, not the absolute times, which depend on the machine. Differences under about 10% on a single run are inside the noise here. One run of each benchmark so far: treat close calls as level.
Every operation at a glance (2026-11-09)
Mean times. "Usual" is the hand-written form most code uses; "best" is the fastest hand-written form found.
| Operation | ARX | Raw SqlClient | Dapper | EF Core | ARX vs raw |
|---|---|---|---|---|---|
| Create, one row | 2.65 ms | 2.57 ms | 2.58 ms | 3.83 ms | level (1.03×) |
| CreateMultiple, 100 rows, ids back | 6.28 ms | usual 24.5 ms, best 8.18 ms | – | 24.0 ms | 3.9× faster than usual, 0.77× best |
| CreateMultiple, 1,000 rows, ids back | 35.5 ms | usual 437 ms, best 31.8 ms | – | 286 ms | 12× faster than usual, 1.12× best |
| CreateMultiple, 10,000 rows, ids back | 339 ms | usual 4.43 s, best 345 ms | – | 1.85 s | level with best |
| CreateMultiple, 10,000 rows, no ids needed | 365 ms (still returns ids) | SqlBulkCopy 111 ms |
one statement a row: 27.2 s | – | 3.3× SqlBulkCopy |
| Update, one row | 2.67–2.86 ms | 2.47–2.78 ms | 2.76 ms | 3.72 ms | 0.96–1.16× (two runs) |
| UpdateMultiple, 100 rows | 6.23 ms | 5.73 ms | 273 ms | 25.0 ms | 1.09× |
| UpdateMultiple, 1,000 rows | 27.8 ms | 23.2 ms | 2.52 s | 262 ms | 1.20× |
| UpdateMultiple, 10,000 rows | 269–279 ms | 219–261 ms | 25.7 s | 1.96 s | 1.07–1.23× (two runs) |
| Delete, one row | 4.38–4.74 ms | 4.20–4.66 ms | 4.14 ms | 12.4 ms | 0.96–1.12× (three runs) |
| DeleteMultiple, 100 ids | 4.87 ms | IN list 5.89 ms | 6.12 ms | 15.1 ms | 0.83× |
| DeleteMultiple, 1,000 ids | 10.5–11.5 ms | IN list 180 ms | 174 ms | 264 ms | 16× faster |
| DeleteMultiple, 10,000 ids | 52.3 ms | OPENJSON 48.5 ms | 2.27 s | 61.4 ms | level |
| Retrieve, one row by id | 1.60 ms | 1.47 ms | 1.44 ms | 2.12 ms | 1.09× |
| RetrieveMultiple, 100 rows | 1.88 ms | 1.97 ms | 2.76 ms | 2.83 ms | level |
| RetrieveMultiple, 1,000 rows | 5.82 ms | 4.01 ms | 4.97 ms | 5.15 ms | 1.45× (1.17× Dapper) |
| RetrieveMultiple, 10,000 rows | 62.8 ms | typed 34.3 ms | 64.4 ms | 61.0 ms | 1.83× typed; level with Dapper and EF Core |
| A page of 50 with the total | 1.76–2.88 ms | 2.68–2.73 ms | – | – | level |
| Execute: a procedure, 1 row + OUTPUT values | 3.24 ms | 3.25 ms | 2.96 ms | no way to read OUTPUT values | level |
| Execute: a procedure, 1,000 rows | 4.78 ms | 4.06 ms | 4.04 ms | – | 1.18× |
| Execute: a scalar function | 1.47–1.81 ms | 1.43–1.51 ms | – | – | 1.03–1.20× |
"Usual" CreateMultiple is a multi-row INSERT … OUTPUT of up to 2,000 parameters a statement (ids unordered); "best"
is a hand-written MERGE from one OPENJSON parameter returning ids in list order, which is what ARX sends for groups
of 20 rows or more. The Dapper CreateMultiple and UpdateMultiple columns are ExecuteAsync(sql, list), one statement
per row: what Dapper does with a list.
What the numbers say
- Single-row calls are level with raw SqlClient and Dapper (0.96–1.16× across the runs), and 1.3–2.6× faster than EF Core. Getting
Create there needed the plain
OUTPUTchange: the table variable cost about 2 ms a call. - Many-row writes are level with the best hand-written SQL (0.77–1.20×): the JSON row source sends one parameter for any number of rows, so SQL Server compiles one plan and there is no 2,100-parameter limit to split around. Against the usual hand-written SQL (multi-row VALUES) ARX is 4–13× faster, and 4–9× faster than EF Core.
SqlBulkCopyis 3.3× faster for 10,000 rows when ids aren't needed. ARX always returns ids; a bulk path without them would be a new option.- Lists of ids: SQL Server's cost for an IN list climbs faster than the list (a SELECT by 1,000 ids is 28 ms as an IN list, 5 ms as one OPENJSON parameter, with a cached plan). ARX sends lists from 50 values as OPENJSON, so it beats every IN-list approach from 100 ids up (16× at 1,000).
- Reads are level with Dapper and EF Core. A raw typed reader is faster for large results (1.8× at 10,000 rows): ARX builds a dictionary per row, as on PostgreSQL, and allocates 2.3× what the raw reader does.
The reports
BenchmarkDotNet's own output for the runs the summary cites, as committed: every number above comes from one of these.
2026-11-09: full run Create.CreateBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw INSERT … OUTPUT inserted.id' | 2.573 ms | 0.1122 ms | 0.0498 ms | 1.00 | 0.03 | - | 9.34 KB | 1.00 |
| 'Dapper QuerySingle (INSERT … OUTPUT)' | 2.583 ms | 0.1089 ms | 0.0484 ms | 1.00 | 0.03 | - | 8.05 KB | 0.86 |
| 'EF Core Add + SaveChanges' | 3.832 ms | 0.5485 ms | 0.2869 ms | 1.49 | 0.11 | 15.6250 | 94.76 KB | 10.15 |
| 'ARX CreateAsync' | 2.649 ms | 0.2446 ms | 0.1279 ms | 1.03 | 0.05 | - | 17.84 KB | 1.91 |
2026-11-09: full run Create.CreateMultipleBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Categories | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw SqlBulkCopy' | CreateMultiple, ids not needed | 1 | 11.092 ms | 0.5198 ms | 0.2308 ms | 1.00 | 0.03 | - | - | - | 42.25 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 1 | 2.662 ms | 0.2223 ms | 0.1163 ms | 0.24 | 0.01 | - | - | - | 7.74 KB | 0.18 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 1 | 2.873 ms | 0.5769 ms | 0.3018 ms | 0.26 | 0.03 | - | - | - | 16.94 KB | 0.40 |
| 'Raw SqlBulkCopy' | CreateMultiple, ids not needed | 10 | 11.927 ms | 0.5242 ms | 0.2328 ms | 1.00 | 0.03 | - | - | - | 50.31 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 10 | 30.454 ms | 5.7719 ms | 3.0188 ms | 2.55 | 0.24 | - | - | - | 46.55 KB | 0.93 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 10 | 4.220 ms | 0.9844 ms | 0.5149 ms | 0.35 | 0.04 | 7.8125 | - | - | 55.35 KB | 1.10 |
| 'Raw SqlBulkCopy' | CreateMultiple, ids not needed | 100 | 14.761 ms | 1.3903 ms | 0.7271 ms | 1.00 | 0.07 | - | - | - | 135.44 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 100 | 260.672 ms | 35.9391 ms | 15.9572 ms | 17.70 | 1.30 | - | - | - | 434.76 KB | 3.21 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 100 | 7.571 ms | 2.8674 ms | 1.4997 ms | 0.51 | 0.10 | 15.6250 | - | - | 141.11 KB | 1.04 |
| 'Raw SqlBulkCopy' | CreateMultiple, ids not needed | 1000 | 21.389 ms | 2.5601 ms | 1.1367 ms | 1.00 | 0.07 | 218.7500 | 62.5000 | - | 1136.49 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 1000 | 2,594.951 ms | 240.9890 ms | 126.0419 ms | 121.60 | 7.96 | - | - | - | 4316.01 KB | 3.80 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 1000 | 30.811 ms | 1.9229 ms | 1.0057 ms | 1.44 | 0.08 | 156.2500 | 156.2500 | 156.2500 | 1251.34 KB | 1.10 |
| 'Raw SqlBulkCopy' | CreateMultiple, ids not needed | 10000 | 111.099 ms | 22.7953 ms | 11.9224 ms | 1.01 | 0.15 | 1750.0000 | 750.0000 | - | 12168.69 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 10000 | 27,243.522 ms | 1,575.8506 ms | 699.6874 ms | 247.75 | 26.18 | 9000.0000 | - | - | 43131.83 KB | 3.54 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 10000 | 364.627 ms | 35.9055 ms | 18.7793 ms | 3.32 | 0.38 | 1000.0000 | - | - | 12484.52 KB | 1.03 |
| 'Raw multi-row INSERT … OUTPUT (ids unordered)' | CreateMultiple, returns ids | 1 | 2.573 ms | 0.1460 ms | 0.0648 ms | 1.00 | 0.03 | - | - | - | 9.92 KB | 1.00 |
| 'Raw MERGE from OPENJSON, ids in order' | CreateMultiple, returns ids | 1 | 5.306 ms | 0.7502 ms | 0.3331 ms | 2.06 | 0.13 | - | - | - | 8.86 KB | 0.89 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 1 | 3.869 ms | 0.5354 ms | 0.2800 ms | 1.50 | 0.11 | 15.6250 | - | - | 94.75 KB | 9.55 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 1 | 2.756 ms | 0.2904 ms | 0.1289 ms | 1.07 | 0.05 | - | - | - | 16.94 KB | 1.71 |
| 'Raw multi-row INSERT … OUTPUT (ids unordered)' | CreateMultiple, returns ids | 10 | 3.662 ms | 0.5913 ms | 0.2626 ms | 1.00 | 0.09 | 7.8125 | - | - | 48.03 KB | 1.00 |
| 'Raw MERGE from OPENJSON, ids in order' | CreateMultiple, returns ids | 10 | 5.377 ms | 0.2418 ms | 0.1073 ms | 1.47 | 0.10 | - | - | - | 12.71 KB | 0.26 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 10 | 4.584 ms | 0.7304 ms | 0.3820 ms | 1.26 | 0.13 | 39.0625 | 7.8125 | - | 209.63 KB | 4.36 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 10 | 3.480 ms | 0.6085 ms | 0.2702 ms | 0.95 | 0.09 | 7.8125 | - | - | 55.35 KB | 1.15 |
| 'Raw multi-row INSERT … OUTPUT (ids unordered)' | CreateMultiple, returns ids | 100 | 24.499 ms | 2.0911 ms | 1.0937 ms | 1.00 | 0.06 | 83.3333 | - | - | 464.07 KB | 1.00 |
| 'Raw MERGE from OPENJSON, ids in order' | CreateMultiple, returns ids | 100 | 8.176 ms | 0.5162 ms | 0.2700 ms | 0.33 | 0.02 | - | - | - | 56.54 KB | 0.12 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 100 | 24.026 ms | 2.1986 ms | 0.9762 ms | 0.98 | 0.06 | 200.0000 | 66.6667 | - | 1305.03 KB | 2.81 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 100 | 6.275 ms | 0.1607 ms | 0.0573 ms | 0.26 | 0.01 | 23.4375 | - | - | 141.1 KB | 0.30 |
| 'Raw multi-row INSERT … OUTPUT (ids unordered)' | CreateMultiple, returns ids | 1000 | 436.951 ms | 44.2340 ms | 23.1353 ms | 1.00 | 0.07 | 1000.0000 | - | - | 4874.8 KB | 1.00 |
| 'Raw MERGE from OPENJSON, ids in order' | CreateMultiple, returns ids | 1000 | 31.783 ms | 3.9694 ms | 1.7624 ms | 0.07 | 0.01 | 71.4286 | 71.4286 | 71.4286 | 514.59 KB | 0.11 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 1000 | 285.501 ms | 119.1096 ms | 62.2966 ms | 0.65 | 0.14 | 2000.0000 | 1000.0000 | - | 12381.92 KB | 2.54 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 1000 | 35.515 ms | 5.0961 ms | 2.2627 ms | 0.08 | 0.01 | 142.8571 | 142.8571 | 142.8571 | 1251.39 KB | 0.26 |
| 'Raw multi-row INSERT … OUTPUT (ids unordered)' | CreateMultiple, returns ids | 10000 | 4,431.695 ms | 300.4521 ms | 157.1423 ms | 1.00 | 0.05 | 8000.0000 | 7000.0000 | - | 48718.85 KB | 1.00 |
| 'Raw MERGE from OPENJSON, ids in order' | CreateMultiple, returns ids | 10000 | 345.094 ms | 74.0173 ms | 38.7125 ms | 0.08 | 0.01 | - | - | - | 5203.79 KB | 0.11 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 10000 | 1,854.737 ms | 134.8789 ms | 59.8871 ms | 0.42 | 0.02 | 19000.0000 | 6000.0000 | - | 121456.69 KB | 2.49 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 10000 | 339.302 ms | 77.3277 ms | 34.3340 ms | 0.08 | 0.01 | 1000.0000 | - | - | 12480.3 KB | 0.26 |
2026-11-09: full run Delete.DeleteBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
SingleOperation : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=SingleOperation InvocationCount=1 IterationCount=12
LaunchCount=1 RunStrategy=Monitoring UnrollFactor=1
WarmupCount=1
| Method | Rows | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 1 | 4.660 ms | 0.7311 ms | 0.5708 ms | 4.649 ms | 1.01 | 0.17 | - | 4.3 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 1 | 4.448 ms | 1.9072 ms | 1.4891 ms | 4.160 ms | 0.97 | 0.33 | - | 9.84 KB | 2.29 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 1 | 13.717 ms | 31.9640 ms | 24.9554 ms | 6.083 ms | 2.98 | 5.26 | - | 143.98 KB | 33.51 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1 | 4.461 ms | 0.6887 ms | 0.5377 ms | 4.333 ms | 0.97 | 0.16 | - | 8.49 KB | 1.98 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 100 | 6.089 ms | 0.7223 ms | 0.5639 ms | 6.027 ms | 1.01 | 0.12 | - | 43.22 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 100 | 7.240 ms | 3.6444 ms | 2.8453 ms | 6.319 ms | 1.20 | 0.46 | - | 46.21 KB | 1.07 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 100 | 19.187 ms | 27.1563 ms | 21.2019 ms | 13.946 ms | 3.17 | 3.39 | - | 962.21 KB | 22.26 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 100 | 8.034 ms | 7.6499 ms | 5.9726 ms | 6.338 ms | 1.33 | 0.96 | - | 45.91 KB | 1.06 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 1000 | 261.626 ms | 50.1401 ms | 39.1461 ms | 262.899 ms | 1.02 | 0.21 | - | 429.41 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 1000 | 199.019 ms | 32.7524 ms | 25.5709 ms | 192.120 ms | 0.78 | 0.15 | - | 389.53 KB | 0.91 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 1000 | 293.277 ms | 81.1122 ms | 63.3271 ms | 280.950 ms | 1.14 | 0.29 | 15000.0000 | 71562.17 KB | 166.65 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1000 | 197.567 ms | 27.5715 ms | 21.5260 ms | 190.362 ms | 0.77 | 0.14 | - | 390.95 KB | 0.91 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 10000 | 57.818 ms | 12.8123 ms | 10.0030 ms | 53.644 ms | 1.02 | 0.22 | - | 211.43 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 10000 | 2,638.094 ms | 249.4983 ms | 194.7919 ms | 2,580.032 ms | 46.68 | 7.29 | - | 3762.84 KB | 17.80 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 10000 | 62.968 ms | 38.6487 ms | 30.1744 ms | 52.352 ms | 1.11 | 0.54 | - | 715.09 KB | 3.38 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 10000 | 55.393 ms | 7.0285 ms | 5.4874 ms | 54.809 ms | 0.98 | 0.17 | - | 575.36 KB | 2.72 |
2026-11-09: full run Execute.ExecuteBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Categories | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw CommandType.StoredProcedure, reader + OUTPUT' | Procedure | 1 | 3.246 ms | 0.6506 ms | 0.3403 ms | 1.01 | 0.14 | - | - | 4.88 KB | 1.00 |
| 'Dapper QueryAsync + DynamicParameters output' | Procedure | 1 | 2.963 ms | 0.1834 ms | 0.0814 ms | 0.92 | 0.09 | - | - | 6.39 KB | 1.31 |
| 'ARX ExecuteAsync (procedure)' | Procedure | 1 | 3.242 ms | 0.5159 ms | 0.2291 ms | 1.01 | 0.12 | - | - | 12.34 KB | 2.53 |
| 'Raw CommandType.StoredProcedure, reader + OUTPUT' | Procedure | 100 | 3.024 ms | 0.7453 ms | 0.3309 ms | 1.01 | 0.14 | - | - | 9.02 KB | 1.00 |
| 'Dapper QueryAsync + DynamicParameters output' | Procedure | 100 | 2.964 ms | 0.2397 ms | 0.1064 ms | 0.99 | 0.09 | 3.9063 | - | 24.69 KB | 2.74 |
| 'ARX ExecuteAsync (procedure)' | Procedure | 100 | 3.280 ms | 0.5275 ms | 0.2759 ms | 1.09 | 0.13 | 7.8125 | - | 43.98 KB | 4.87 |
| 'Raw CommandType.StoredProcedure, reader + OUTPUT' | Procedure | 1000 | 4.063 ms | 0.5413 ms | 0.2831 ms | 1.00 | 0.09 | 15.6250 | - | 71.4 KB | 1.00 |
| 'Dapper QueryAsync + DynamicParameters output' | Procedure | 1000 | 4.044 ms | 0.2918 ms | 0.1295 ms | 1.00 | 0.07 | 39.0625 | 7.8125 | 186.45 KB | 2.61 |
| 'ARX ExecuteAsync (procedure)' | Procedure | 1000 | 4.776 ms | 1.0221 ms | 0.5346 ms | 1.18 | 0.15 | 62.5000 | 15.6250 | 352.67 KB | 4.94 |
| 'Raw SELECT dbo.fn(@a, @b)' | Scalar function | 1 | 1.508 ms | 0.3528 ms | 0.1845 ms | 1.01 | 0.16 | - | - | 4.96 KB | 1.00 |
| 'ARX ExecuteAsync (scalar function, known scalar)' | Scalar function | 1 | 1.473 ms | 0.0946 ms | 0.0337 ms | 0.99 | 0.11 | - | - | 14.76 KB | 2.98 |
| 'Raw SELECT dbo.fn(@a, @b)' | Scalar function | 100 | 1.430 ms | 0.0934 ms | 0.0415 ms | 1.00 | 0.04 | - | - | 4.96 KB | 1.00 |
| 'ARX ExecuteAsync (scalar function, known scalar)' | Scalar function | 100 | 1.810 ms | 0.6285 ms | 0.3287 ms | 1.27 | 0.22 | - | - | 14.76 KB | 2.98 |
| 'Raw SELECT dbo.fn(@a, @b)' | Scalar function | 1000 | 1.447 ms | 0.1138 ms | 0.0595 ms | 1.00 | 0.05 | - | - | 4.96 KB | 1.00 |
| 'ARX ExecuteAsync (scalar function, known scalar)' | Scalar function | 1000 | 1.713 ms | 0.6749 ms | 0.3530 ms | 1.19 | 0.23 | - | - | 14.76 KB | 2.98 |
2026-11-09: full run Retrieve.RetrieveBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw SqlDataReader by id' | 1.465 ms | 0.1485 ms | 0.0659 ms | 1.00 | 0.06 | - | 7.48 KB | 1.00 |
| 'Dapper QuerySingle<T>' | 1.435 ms | 0.1083 ms | 0.0567 ms | 0.98 | 0.05 | - | 7.91 KB | 1.06 |
| 'EF Core AsNoTracking FirstAsync' | 2.119 ms | 0.4622 ms | 0.2417 ms | 1.45 | 0.17 | 15.6250 | 83.04 KB | 11.11 |
| 'ARX RetrieveAsync by id' | 1.600 ms | 0.2123 ms | 0.1111 ms | 1.09 | 0.08 | - | 10.45 KB | 1.40 |
2026-11-09: full run Retrieve.RetrieveMultipleBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Categories | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw SqlDataReader, id range' | **** | 100 | 1.965 ms | 0.4714 ms | 0.2465 ms | 1.01 | 0.17 | 7.8125 | - | - | 36 KB | 1.00 |
| 'Dapper Query<T>' | 100 | 2.762 ms | 1.4621 ms | 0.7647 ms | 1.42 | 0.41 | 7.8125 | - | - | 47.77 KB | 1.33 | |
| 'EF Core AsNoTracking ToListAsync' | 100 | 2.826 ms | 0.7908 ms | 0.4136 ms | 1.46 | 0.26 | 27.3438 | 3.9063 | - | 135.79 KB | 3.77 | |
| 'ARX RetrieveMultipleAsync' | 100 | 1.883 ms | 0.2559 ms | 0.1339 ms | 0.97 | 0.13 | 15.6250 | - | - | 85.48 KB | 2.37 | |
| 'Raw SqlDataReader, id range' | **** | 1000 | 4.005 ms | 0.2886 ms | 0.1029 ms | 1.00 | 0.03 | 62.5000 | 15.6250 | - | 307.51 KB | 1.00 |
| 'Dapper Query<T>' | 1000 | 4.967 ms | 1.3939 ms | 0.7291 ms | 1.24 | 0.17 | 85.9375 | 23.4375 | - | 406.45 KB | 1.32 | |
| 'EF Core AsNoTracking ToListAsync' | 1000 | 5.154 ms | 0.8229 ms | 0.3654 ms | 1.29 | 0.09 | 125.0000 | 31.2500 | - | 581.63 KB | 1.89 | |
| 'ARX RetrieveMultipleAsync' | 1000 | 5.822 ms | 1.6390 ms | 0.7277 ms | 1.45 | 0.17 | 132.8125 | 70.3125 | - | 729.66 KB | 2.37 | |
| 'Raw SqlDataReader, id range' | **** | 10000 | 34.337 ms | 2.9009 ms | 1.2880 ms | 1.00 | 0.05 | 500.0000 | 285.7143 | 142.8571 | 3176.05 KB | 1.00 |
| 'Dapper Query<T>' | 10000 | 64.421 ms | 27.0459 ms | 12.0086 ms | 1.88 | 0.33 | 666.6667 | 166.6667 | - | 4101.41 KB | 1.29 | |
| 'EF Core AsNoTracking ToListAsync' | 10000 | 61.003 ms | 10.7037 ms | 5.5983 ms | 1.78 | 0.17 | 888.8889 | 333.3333 | 111.1111 | 5187.86 KB | 1.63 | |
| 'ARX RetrieveMultipleAsync' | 10000 | 62.835 ms | 11.5098 ms | 6.0199 ms | 1.83 | 0.18 | 1000.0000 | 333.3333 | - | 7325.21 KB | 2.31 | |
| 'Raw page of 50 + COUNT_BIG in one command' | Page | 100 | 2.728 ms | 0.6278 ms | 0.3284 ms | ? | ? | - | - | - | 11.11 KB | ? |
| 'ARX page of 50 with the total' | Page | 100 | 2.696 ms | 0.6224 ms | 0.3255 ms | ? | ? | 7.8125 | - | - | 48.59 KB | ? |
| 'Raw page of 50 + COUNT_BIG in one command' | Page | 1000 | 2.675 ms | 0.9820 ms | 0.5136 ms | ? | ? | - | - | - | 11.18 KB | ? |
| 'ARX page of 50 with the total' | Page | 1000 | 1.760 ms | 0.1474 ms | 0.0654 ms | ? | ? | 7.8125 | - | - | 49.09 KB | ? |
| 'Raw page of 50 + COUNT_BIG in one command' | Page | 10000 | 2.676 ms | 0.1706 ms | 0.0758 ms | ? | ? | - | - | - | 11.18 KB | ? |
| 'ARX page of 50 with the total' | Page | 10000 | 2.882 ms | 0.1991 ms | 0.0884 ms | ? | ? | 7.8125 | - | - | 49.09 KB | ? |
2026-11-09: full run Update.UpdateBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 1 | 2.776 ms | 0.2486 ms | 0.1104 ms | 1.00 | 0.05 | - | - | - | 7.44 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 1 | 2.758 ms | 0.6379 ms | 0.3336 ms | 0.99 | 0.12 | - | - | - | 7.88 KB | 1.06 |
| 'EF Core Attach, all modified, SaveChanges' | 1 | 3.721 ms | 0.7511 ms | 0.3928 ms | 1.34 | 0.14 | 15.6250 | - | - | 93.45 KB | 12.56 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 1 | 2.667 ms | 0.2983 ms | 0.1560 ms | 0.96 | 0.06 | 3.9063 | - | - | 20.82 KB | 2.80 |
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 100 | 5.730 ms | 0.6723 ms | 0.2985 ms | 1.00 | 0.07 | 7.8125 | - | - | 55.44 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 100 | 272.551 ms | 50.2837 ms | 26.2993 ms | 47.68 | 4.93 | - | - | - | 455.01 KB | 8.21 |
| 'EF Core Attach, all modified, SaveChanges' | 100 | 25.031 ms | 2.8022 ms | 1.4656 ms | 4.38 | 0.32 | 281.2500 | 156.2500 | - | 1484.94 KB | 26.78 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 100 | 6.227 ms | 0.5707 ms | 0.2534 ms | 1.09 | 0.07 | 39.0625 | - | - | 197.25 KB | 3.56 |
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 1000 | 23.225 ms | 1.1770 ms | 0.5226 ms | 1.00 | 0.03 | 125.0000 | 125.0000 | 125.0000 | 505.06 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 1000 | 2,519.392 ms | 297.9777 ms | 155.8481 ms | 108.53 | 6.73 | - | - | - | 4519.06 KB | 8.95 |
| 'EF Core Attach, all modified, SaveChanges' | 1000 | 262.143 ms | 20.6203 ms | 9.1555 ms | 11.29 | 0.44 | 2000.0000 | 1000.0000 | - | 14333.52 KB | 28.38 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 1000 | 27.762 ms | 1.9036 ms | 0.8452 ms | 1.20 | 0.04 | 218.7500 | 187.5000 | 187.5000 | 1624.64 KB | 3.22 |
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 10000 | 260.837 ms | 43.1129 ms | 22.5489 ms | 1.01 | 0.12 | - | - | - | 5095 KB | 1.00 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 10000 | 25,701.101 ms | 1,345.6910 ms | 703.8224 ms | 99.17 | 8.36 | 9000.0000 | - | - | 45163 KB | 8.86 |
| 'EF Core Attach, all modified, SaveChanges' | 10000 | 1,958.254 ms | 43.1085 ms | 22.5466 ms | 7.56 | 0.61 | 22000.0000 | 6000.0000 | - | 140732.24 KB | 27.62 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 10000 | 279.359 ms | 55.8392 ms | 29.2050 ms | 1.08 | 0.14 | 1000.0000 | - | - | 15764.65 KB | 3.09 |
2026-11-09: delete after json list
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
SingleOperation : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=SingleOperation InvocationCount=1 IterationCount=12
LaunchCount=1 RunStrategy=Monitoring UnrollFactor=1
WarmupCount=1
| Method | Rows | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 1 | 4.227 ms | 0.4015 ms | 0.3135 ms | 4.159 ms | 1.00 | 0.10 | - | 4.3 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 1 | 4.141 ms | 0.5743 ms | 0.4484 ms | 4.224 ms | 0.98 | 0.12 | - | 9.84 KB | 2.29 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 1 | 12.394 ms | 29.5451 ms | 23.0669 ms | 5.743 ms | 2.95 | 5.29 | - | 143.87 KB | 33.48 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1 | 4.741 ms | 2.7870 ms | 2.1759 ms | 4.316 ms | 1.13 | 0.50 | - | 8.49 KB | 1.98 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 100 | 5.893 ms | 0.6621 ms | 0.5169 ms | 5.742 ms | 1.01 | 0.11 | - | 43.22 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 100 | 6.117 ms | 0.5990 ms | 0.4677 ms | 6.223 ms | 1.04 | 0.11 | - | 46.21 KB | 1.07 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 100 | 15.082 ms | 29.3712 ms | 22.9311 ms | 8.494 ms | 2.58 | 3.78 | - | 957.52 KB | 22.16 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 100 | 4.871 ms | 0.5796 ms | 0.4525 ms | 5.036 ms | 0.83 | 0.10 | - | 30.48 KB | 0.71 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 1000 | 179.936 ms | 37.3685 ms | 29.1749 ms | 171.849 ms | 1.02 | 0.21 | - | 429.41 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 1000 | 173.736 ms | 23.5722 ms | 18.4036 ms | 167.053 ms | 0.99 | 0.16 | - | 389.53 KB | 0.91 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 1000 | 264.382 ms | 73.7299 ms | 57.5634 ms | 255.136 ms | 1.50 | 0.37 | 15000.0000 | 71562.17 KB | 166.65 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1000 | 11.450 ms | 3.5477 ms | 2.7698 ms | 10.397 ms | 0.06 | 0.02 | - | 86.73 KB | 0.20 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 10000 | 48.520 ms | 5.7111 ms | 4.4588 ms | 46.869 ms | 1.01 | 0.12 | - | 211.43 KB | 1.00 |
| 'Dapper ExecuteAsync(DELETE … IN @ids)' | 10000 | 2,271.462 ms | 168.7610 ms | 131.7575 ms | 2,277.816 ms | 47.15 | 4.69 | - | 3762.84 KB | 17.80 |
| 'EF Core ExecuteDeleteAsync (Where ids.Contains)' | 10000 | 61.437 ms | 40.4206 ms | 31.5578 ms | 50.312 ms | 1.28 | 0.64 | - | 715.09 KB | 3.38 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 10000 | 52.294 ms | 5.3645 ms | 4.1882 ms | 51.580 ms | 1.09 | 0.12 | - | 575.36 KB | 2.72 |
probes in list vs openjson
Probe: an IN list of parameters against one OPENJSON parameter (2026-11-09)
The source is in-list-vs-openjson.cs.txt (a console program with Microsoft.Data.SqlClient
7.1.1, run against arx_bench on arx-mssql). A 10,000-row table keyed by bigint; ids every third row. Medians of 10
runs after 2 warm-ups. SELECT runs with a cached plan; each DELETE follows a TRUNCATE and reload (as the benchmark's
iteration setup), so its plan is recompiled, as it is when a table's statistics change.
| Values | SELECT, IN list | SELECT, OPENJSON | DELETE, IN list | DELETE, OPENJSON |
|---|---|---|---|---|
| 20 | 2.09 ms | 1.99 ms | 3.71 ms | 4.07 ms |
| 50 | 2.45 ms | 2.33 ms | 5.29 ms | 4.96 ms |
| 100 | 2.97 ms | 2.76 ms | 4.79 ms | 4.00 ms |
| 200 | 4.62 ms | 2.85 ms | 6.06 ms | 4.73 ms |
| 500 | 11.10 ms | 4.38 ms | 67.85 ms | 6.22 ms |
| 1,000 | 28.09 ms | 5.07 ms | 162.87 ms | 9.39 ms |
| 2,000 | 116.67 ms | 9.56 ms | 507.79 ms | 13.53 ms |
Level at 20 to 50 values; past that the IN list's cost climbs much faster than the list. Decision: lists from 50 values
go as OPENJSON (JSON_MIN_LIST), for DeleteMultiple's ids and for Retrieve's In conditions. Confirmed by the Delete
benchmark: 2026-11-09-delete-after-json-list.md.
2026-11-09: update after read committed
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 1 | 2.467 ms | 0.1942 ms | 0.0862 ms | 1.00 | 0.05 | - | - | - | 7.44 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 1 | 2.862 ms | 0.4251 ms | 0.2223 ms | 1.16 | 0.09 | 3.9063 | - | - | 21.45 KB | 2.88 |
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 100 | 5.644 ms | 0.3997 ms | 0.1775 ms | 1.00 | 0.04 | 7.8125 | - | - | 55.43 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 100 | 6.137 ms | 0.1583 ms | 0.0828 ms | 1.09 | 0.03 | 39.0625 | - | - | 199.34 KB | 3.60 |
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 1000 | 24.207 ms | 4.3628 ms | 2.2818 ms | 1.01 | 0.12 | 125.0000 | 125.0000 | 125.0000 | 504.79 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 1000 | 27.591 ms | 1.6681 ms | 0.8725 ms | 1.15 | 0.10 | 218.7500 | 187.5000 | 187.5000 | 1626.76 KB | 3.22 |
| 'Raw UPDATE … FROM OPENJSON (one row: plain UPDATE)' | 10000 | 219.250 ms | 19.6629 ms | 8.7304 ms | 1.00 | 0.05 | - | - | - | 5094.51 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 10000 | 268.612 ms | 46.0340 ms | 24.0767 ms | 1.23 | 0.11 | 1000.0000 | - | - | 15759.68 KB | 3.09 |
2026-11-09: delete after read committed
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
SingleOperation : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=SingleOperation InvocationCount=1 IterationCount=12
LaunchCount=1 RunStrategy=Monitoring UnrollFactor=1
WarmupCount=1
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 1 | 4.200 ms | 0.8484 ms | 0.6624 ms | 1.02 | 0.23 | 3.77 KB | 1.00 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1 | 4.375 ms | 1.6954 ms | 1.3236 ms | 1.07 | 0.36 | 8.73 KB | 2.31 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 100 | 6.209 ms | 0.6483 ms | 0.5062 ms | 1.01 | 0.11 | 39.65 KB | 1.00 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 100 | 5.224 ms | 0.5193 ms | 0.4054 ms | 0.85 | 0.09 | 14.79 KB | 0.37 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 1000 | 174.962 ms | 29.0603 ms | 22.6884 ms | 1.01 | 0.17 | 397.77 KB | 1.00 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1000 | 10.482 ms | 1.3902 ms | 1.0854 ms | 0.06 | 0.01 | 71.05 KB | 0.18 |
| 'Raw DELETE … IN (…) (past 2,000: OPENJSON)' | 10000 | 50.426 ms | 7.5546 ms | 5.8981 ms | 1.01 | 0.15 | 99.36 KB | 1.00 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 10000 | 58.566 ms | 18.8074 ms | 14.6836 ms | 1.17 | 0.31 | 463.63 KB | 4.67 |
Run them yourself
The benchmark code is published, so you can check these numbers on your own machine and database: arx-benchmark-mssql.zip. It builds against the ARX packages on nuget.org; HOW-TO-RUN.md inside says how to point it at a database and run it. Compare the ratios, not the absolute times.