Skip to content

Commit fdc5bf3

Browse files
authored
docs: improve newcomer onboarding and performance story (#196)
1 parent 36610d7 commit fdc5bf3

11 files changed

Lines changed: 443 additions & 340 deletions

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ include = [
3838
"examples/**",
3939
"docs/README.md",
4040
"docs/benchmarks.md",
41+
"docs/getting-started.md",
4142
"docs/integration-tests.md",
4243
"docs/observability.md",
44+
"docs/performance.md",
4345
"docs/type-mapping.md",
4446
]
4547

README.md

Lines changed: 81 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,78 @@
1-
# Arrow SQL Server
1+
<h1 align="center">Arrow SQL Server</h1>
22

3-
[![Crates.io](https://img.shields.io/crates/v/arrow-sql-server.svg)](https://crates.io/crates/arrow-sql-server)
4-
[![Docs.rs](https://docs.rs/arrow-sql-server/badge.svg)](https://docs.rs/arrow-sql-server)
5-
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
3+
<p align="center">
4+
<a href="https://crates.io/crates/arrow-sql-server"><img alt="Crates.io" src="https://img.shields.io/crates/v/arrow-sql-server.svg"></a>
5+
<a href="https://docs.rs/arrow-sql-server"><img alt="Docs.rs" src="https://docs.rs/arrow-sql-server/badge.svg"></a>
6+
<a href="LICENSE"><img alt="Apache 2.0 license" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
7+
</p>
68

7-
Arrow SQL Server is a high-performance Apache Arrow `RecordBatch` bulk writer
8-
for Microsoft SQL Server, built on the Tiberius TDS driver.
9+
<p align="center">
10+
<strong>Bulk-write Apache Arrow RecordBatch values to Microsoft SQL Server without an ODBC driver.</strong>
11+
</p>
912

10-
The current API focuses on Arrow-to-SQL Server writes:
13+
<h2 align="center">
14+
Up to 4x faster than Arrow ODBC.<br>
15+
Uses 92% less memory.
16+
</h2>
1117

12-
- plan SQL Server-compatible schemas from Arrow schemas,
13-
- render deterministic `CREATE TABLE` SQL,
14-
- report unsupported mappings as structured diagnostics,
15-
- write Arrow `RecordBatch` values with a selectable SQL Server bulk writer,
16-
- emit sanitized writer and protocol tracing through `tracing`.
18+
<p align="center">
19+
Measured up to 3.9x the throughput of Arrow ODBC.<br>
20+
A fresh 0.3.0 run measured 2.67x the throughput and 17 MiB versus 213 MiB peak memory.<br>
21+
<a href="docs/performance.md">See the results, limitations, and reproduction command.</a>
22+
</p>
1723

18-
SQL Server-to-Arrow reads are reserved for a later release.
24+
Arrow SQL Server is a Rust library for schema-aware, asynchronous SQL Server
25+
bulk loading. It plans Arrow schemas, generates SQL Server DDL, validates target
26+
tables, and writes batches through a direct Arrow-to-TDS path.
1927

20-
## Install
21-
22-
```toml
23-
[dependencies]
24-
arrow-sql-server = "0.3"
25-
```
28+
## Why Arrow SQL Server?
2629

27-
## Quick Start
30+
- **Built for Arrow:** write `RecordBatch` values directly instead of converting
31+
them into application row objects.
32+
- **Built for SQL Server:** explicit type planning, compatibility profiles,
33+
quoted identifiers, target-table validation, and bulk-load diagnostics.
34+
- **No ODBC runtime:** the production path uses TDS through Tiberius, so your
35+
application does not need unixODBC or a Microsoft ODBC driver.
2836

29-
Plan an Arrow schema and render SQL Server DDL:
37+
## Is It a Good Fit?
3038

31-
```rust
32-
use arrow_schema::{DataType, Field, Schema};
33-
use arrow_sql_server::{
34-
CompatibilityLevel, MssqlProfile, MssqlVersion, PlanOptions, TableName,
35-
create_table_sql_from_mappings,
36-
};
39+
| Use Arrow SQL Server when you need | This crate does not provide |
40+
| --- | --- |
41+
| Arrow-to-SQL Server bulk writes from Rust | SQL Server-to-Arrow reads |
42+
| Streaming writes across one or more batches | Connection pooling, retries, or job orchestration |
43+
| SQL Server-aware schema planning and DDL | A database-agnostic writer abstraction |
44+
| A direct TDS path without an ODBC deployment | Migrations, an ORM, or automatic table publishing workflows |
3745

38-
fn main() -> arrow_sql_server::Result<()> {
39-
let schema = Schema::new(vec![
40-
Field::new("id", DataType::Int64, false),
41-
Field::new("name", DataType::Utf8, true),
42-
]);
46+
The crate can generate `CREATE TABLE` SQL, but it does not create or replace a
47+
table unless your application explicitly executes that SQL.
4348

44-
let profile = MssqlProfile::new(
45-
MssqlVersion::SqlServer2022,
46-
CompatibilityLevel::SQL_SERVER_2022,
47-
)?;
48-
let outcome = profile.plan_arrow_schema(&schema, PlanOptions::default())?;
49+
## Install
4950

50-
let table = TableName::new("dbo", "people")?;
51-
let ddl = create_table_sql_from_mappings(&table, outcome.mappings());
51+
Arrow SQL Server 0.3 uses Arrow 58 types. Add the crates used by the examples:
5252

53-
assert!(ddl.contains("CREATE TABLE [dbo].[people]"));
54-
Ok(())
55-
}
53+
```bash
54+
cargo add arrow-sql-server@0.3 arrow-array@58 arrow-schema@58
55+
cargo add tokio@1 --features macros,rt
5656
```
5757

58-
Write a batch to an existing SQL Server table:
58+
The minimum supported Rust version is 1.88.
59+
60+
## Write a Batch
61+
62+
The target table must already match the planned schema. New applications should
63+
use `WriteOptions::default()`; its `Auto` backend selects the optimized writer.
5964

6065
```rust
6166
use arrow_array::RecordBatch;
6267
use arrow_sql_server::{
6368
CompatibilityLevel, MssqlProfile, MssqlVersion, PlanOptions, TableName,
64-
WriteBackend, WriteOptions, connect_mssql_client_from_ado_string,
69+
WriteOptions, WriteStats, connect_mssql_client_from_ado_string,
6570
};
6671

6772
async fn write_batch(
6873
connection_string: &str,
6974
batch: &RecordBatch,
70-
) -> arrow_sql_server::Result<()> {
71-
let mut client = connect_mssql_client_from_ado_string(connection_string).await?;
75+
) -> arrow_sql_server::Result<WriteStats> {
7276
let profile = MssqlProfile::new(
7377
MssqlVersion::SqlServer2022,
7478
CompatibilityLevel::SQL_SERVER_2022,
@@ -78,151 +82,51 @@ async fn write_batch(
7882
.into_value();
7983

8084
let table = TableName::new("dbo", "people")?;
85+
let mut client = connect_mssql_client_from_ado_string(connection_string).await?;
8186
let mut writer = client
82-
.bulk_writer(
83-
table,
84-
planned_schema,
85-
WriteOptions {
86-
backend: WriteBackend::DirectRawBulk,
87-
..WriteOptions::default()
88-
},
89-
)
87+
.bulk_writer(table, planned_schema, WriteOptions::default())
9088
.await?;
9189

9290
writer.write_batch(batch).await?;
93-
writer.finish().await?;
94-
Ok(())
91+
writer.finish().await
9592
}
9693
```
9794

98-
The connected writer validates target table metadata before sending rows. It
99-
does not create the target table automatically; callers can use the DDL helper
100-
when they want this crate to produce the table definition.
101-
102-
## Diagnostics
103-
104-
Planning and write failures return structured diagnostics instead of requiring
105-
string parsing. Diagnostics include severity, machine-readable code, field
106-
context, row context when available, and message text.
107-
108-
For user-facing write failure reports, use `Error::safe_error_info()`. It
109-
exposes the write phase, inner error kind, sanitized summary, diagnostic codes,
110-
and structured diagnostics when available while keeping dependency source text
111-
out of default reports.
112-
113-
For the complete planning surface, see
114-
[Arrow to SQL Server Type Mapping](docs/type-mapping.md).
115-
116-
## Writer Backends
117-
118-
`WriteBackend` controls how planned Arrow rows are sent to SQL Server:
119-
120-
| Backend | Purpose |
121-
| --- | --- |
122-
| `Auto` | Default selection. Currently resolves to `DirectRawBulk`. |
123-
| `BaselineTokenRow` | Compatibility path using Tiberius `TokenRow` bulk load. |
124-
| `DirectFramedBulk` | Direct Arrow-to-TDS row encoding through Tiberius framed writes. |
125-
| `DirectRawBulk` | Optimized direct encoder plus raw bulk packet writes from the Tiberius fork. |
95+
For a complete first run that creates a table, writes a batch, and verifies the
96+
row count, follow [Getting Started](docs/getting-started.md).
12697

127-
The direct raw backend is the optimized production path for currently supported
128-
mappings. The baseline backend remains useful for compatibility checks and
129-
parity tests.
98+
## Supported Data
13099

131-
## Observability
100+
The default planner and both production writers support common Arrow scalar
101+
types, including:
132102

133-
Arrow SQL Server emits structured spans and events through `tracing` for schema
134-
planning, writer initialization, batch writes, direct raw backend summaries,
135-
and writer finish. It never installs a subscriber.
103+
- booleans and signed or unsigned integers,
104+
- floating-point values,
105+
- UTF-8 and binary arrays, including Arrow view arrays,
106+
- decimal values up to SQL Server precision 38,
107+
- dates, times, timestamps, and timezone-aware timestamps.
136108

137-
Its `tiberius-raw-bulk` dependency also emits sanitized protocol tracing under
138-
the `tiberius_raw_bulk::protocol` target. Those protocol events are emitted
139-
inside active `arrow_sql_server` writer spans during connect, bulk-load, and
140-
finish operations.
109+
Nested Arrow values and SQL Server-to-Arrow reads are not currently supported.
110+
See the [complete type-mapping reference](docs/type-mapping.md) for policies,
111+
runtime checks, and unsupported types.
141112

142-
See [Observability](docs/observability.md) for subscriber setup, span and event
143-
names, safe field categories, redaction guarantees, and workflow integration.
113+
SQL Server profiles cover SQL Server 2016, 2017, 2019, 2022, and 2025 with
114+
compatibility-level validation.
144115

145-
## Examples
116+
## Learn More
146117

147-
Compile-checked examples that do not require SQL Server:
118+
Start here:
148119

149-
```bash
150-
cargo run --example schema_to_ddl
151-
cargo run --example planning_diagnostics
152-
cargo run --example backend_selection
153-
cargo run --example policy_dependent_planning
154-
```
155-
156-
SQL Server write example:
157-
158-
```bash
159-
ARROW_SQL_SERVER_EXAMPLE_MSSQL_URL='server=tcp:localhost,1433;user=sa;password=...;TrustServerCertificate=true' \
160-
cargo run --example sqlserver_batch_write
161-
```
162-
163-
By default, the SQL Server example creates, writes to, and drops
164-
`[dbo].[arrow_sql_server_example_write]`.
165-
166-
## Compatibility
167-
168-
Choose the `MssqlProfile` that matches the SQL Server version and database
169-
compatibility level you plan to write against:
170-
171-
```rust
172-
use arrow_sql_server::{CompatibilityLevel, MssqlProfile, MssqlVersion};
173-
174-
let profile = MssqlProfile::new(
175-
MssqlVersion::SqlServer2022,
176-
CompatibilityLevel::SQL_SERVER_2022,
177-
)?;
178-
```
179-
180-
The profile surface models SQL Server 2016, 2017, 2019, 2022, and 2025
181-
version/compatibility-level pairs. Legacy convenience constructors such as
182-
`MssqlProfile::sql_server_2016_compat_100()` and
183-
`MssqlProfile::sql_server_2017_compat_100()` remain available for callers that
184-
target those exact environments.
185-
186-
Arrow SQL Server depends on the published `tiberius-raw-bulk` package as the
187-
crate name `tiberius` and owns that compatibility boundary internally:
188-
189-
```toml
190-
tiberius = { package = "tiberius-raw-bulk", version = "=0.12.3-raw-bulk.15", default-features = false, features = [
191-
"tds73",
192-
"winauth",
193-
"native-tls",
194-
] }
195-
```
196-
197-
Downstream crates should normally depend only on `arrow-sql-server` and construct
198-
SQL Server clients through `connect_mssql_client_from_ado_string` or
199-
`ConnectedMssqlClient`.
200-
201-
## Feature Flags
202-
203-
| Feature | Default | Purpose |
204-
| --- | --- | --- |
205-
| `bench-profile` | no | Enables benchmark-only direct write profiling hooks and forwards to `tiberius/bulk-load-profile`. |
206-
| `integration-tests` | no | Enables SQL Server integration tests that require explicit environment setup or the xtask runner. |
207-
208-
## Validation
209-
210-
Default local validation does not require SQL Server:
211-
212-
```bash
213-
cargo fmt --check
214-
cargo clippy --workspace --all-targets --all-features -- -D warnings
215-
cargo test --workspace
216-
```
217-
218-
Run SQL Server integration tests through the xtask harness:
219-
220-
```bash
221-
cargo xtask sqlserver-test
222-
cargo xtask sqlserver-compat-probe
223-
```
120+
- [Getting Started](docs/getting-started.md): complete your first SQL Server
121+
write.
122+
- [Type Mapping Reference](docs/type-mapping.md): check supported Arrow and SQL
123+
Server types.
124+
- [Performance](docs/performance.md): understand the benchmark claim and its
125+
workload boundaries.
126+
- [API Documentation](https://docs.rs/arrow-sql-server): browse public Rust
127+
types and methods.
224128

225-
## Documentation
129+
Advanced and maintainer documentation:
226130

227-
See [Documentation Index](docs/README.md) for the maintained user and maintainer
228-
docs.
131+
- [Observability](docs/observability.md)
132+
- [Documentation Index](docs/README.md)

docs/README.md

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
# Documentation
22

3-
This directory contains maintained user and maintainer documentation for
4-
Arrow SQL Server.
5-
6-
## User Guides
7-
8-
- [Arrow to SQL Server Type Mapping](type-mapping.md): supported Arrow-to-SQL
9-
Server mappings, policy-dependent mappings, and writer support.
10-
- [Observability](observability.md): tracing setup, stable spans/events, safe
11-
fields, and redaction policy.
12-
- [Integration Tests](integration-tests.md): how to run SQL Server integration
13-
tests with the xtask harness.
14-
- [Writer Benchmarks](benchmarks.md): how to run local writer benchmark commands
15-
and interpret their output.
16-
17-
## Scope
18-
19-
The documentation intentionally focuses on the current crate surface and
20-
repeatable workflows. Historical design notes, issue work logs, dependency
21-
audit baselines, and one-off local benchmark records are kept out of the
22-
published docs.
3+
Choose the document that matches what you are trying to do.
4+
5+
## Start Here
6+
7+
- [Getting Started](getting-started.md): create a table, write your first Arrow
8+
batch, and verify the stored rows.
9+
- [README](../README.md): decide whether Arrow SQL Server fits your application.
10+
11+
## Reference
12+
13+
- [API Documentation](https://docs.rs/arrow-sql-server): public Rust types,
14+
methods, and modules.
15+
- [Type Mapping](type-mapping.md): Arrow-to-SQL Server mappings, conversion
16+
policies, runtime checks, and unsupported types.
17+
18+
## Advanced Guides
19+
20+
- [Performance](performance.md): benchmark results, methodology, limitations,
21+
and reproduction steps.
22+
- [Observability](observability.md): tracing setup, stable spans and events,
23+
safe fields, and redaction guarantees.
24+
25+
## Maintainer Guides
26+
27+
- [Integration Tests](integration-tests.md): run the SQL Server container and
28+
compatibility test suites.
29+
- [Writer Benchmarks](benchmarks.md): run and interpret the local comparison
30+
harness.
31+
32+
Historical design notes, issue work logs, dependency audits, and raw benchmark
33+
logs are intentionally kept out of the user documentation.

docs/benchmarks.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
# Writer Benchmarks
22

3-
The writer benchmark harness lives under `cargo xtask writer-bench`. It is for
4-
SQL Server write-path comparisons only. It does not benchmark reads, exports,
5-
object storage, or general database query performance.
3+
This is a maintainer guide for the `cargo xtask writer-bench` harness. For
4+
curated user-facing results and the headline claim, read
5+
[Performance](performance.md).
6+
7+
The harness is for SQL Server write-path comparisons only. It does not
8+
benchmark reads, exports, object storage, or general database query
9+
performance.
610

711
Benchmark results are local to the machine, container runtime, SQL Server image,
812
network path, row count, batch size, and scenario used for the run. Treat local
913
output as evidence for that run only, not as a portable performance claim.
1014

11-
Historical one-off benchmark notes are intentionally not kept in the published
12-
documentation. Keep new comparison output in `target/` or another ignored path
13-
unless it becomes a maintained user-facing result.
15+
Keep raw comparison output in `target/` or another ignored path. Promote only
16+
reviewed, reproducible results into the maintained performance explanation.
1417

1518
## Prerequisites
1619

0 commit comments

Comments
 (0)