Skip to main content
Version: Next

Configuration Reference

Connection Pool Settings​

SettingTypeDefaultRangeDescription
mssql_connection_limitBIGINT64≥1Max connections per attached database
mssql_connection_cacheBOOLEANtrue-Enable connection pooling and reuse
mssql_reset_connectionBOOLEANtrue-Reset session state when a connection returns to the pool (details)
mssql_connection_timeoutBIGINT30≥0Connection timeout (seconds): the TCP dial and every login-phase read after it (PRELOGIN, TLS, LOGIN7 / FEDAUTH), for ATTACH validation and for every pool refill. 0 means the 30 s default, not "no timeout": a dial or a login read that never completes must not hang a pool refill.
mssql_idle_timeoutBIGINT300≥0Idle connection timeout (seconds, 0=none)
mssql_min_connectionsBIGINT0≥0Connections opened at ATTACH — their logins in parallel, so N cost about one — and kept open while idle. Also the min_connections ATTACH option. Not opened under lazy_validation.
mssql_acquire_timeoutBIGINT30≥0How long a query waits for a pooled connection to be released when the pool is at its limit. Not how long a failed connection takes to report: a connection the pool cannot create — wrong password, expired Azure AD token, refused dial — fails at once with the reason (could not create a connection: Login failed for user 'sa'.) when nothing is active, and with others active the pool keeps waiting for a release but retries creation on a backoff.
mssql_query_timeoutBIGINT30≥0Query execution timeout (seconds, 0=infinite): a scan, mssql_exec, and each INSERT / UPDATE / DELETE statement the extension sends row by row (until spec 080 those waited a fixed 30 s whatever this said, and a timed-out one is cancelled and fails like any failed statement). Not applied to an UPDATE / DELETE / INSERT … SELECT sent to the server whole: it waits as long as the statement takes and is cancelled with the query (Ctrl-C)
mssql_metadata_timeoutBIGINT300≥0Metadata query timeout (seconds, 0=no timeout)
mssql_catalog_cache_ttlBIGINT0≥0Metadata cache TTL (seconds, 0=manual)
mssql_exec_invalidate_cacheBOOLEANfalsetrue/falseAuto-invalidate the catalog cache after DDL run via mssql_exec(). Default false (like the Postgres extension's postgres_execute): invalidate manually with mssql_invalidate_cache() after schema-changing DDL. Set true to auto-invalidate.
mssql_attach_validation_timeoutBIGINT0≥0ATTACH-time eager-validation timeout (seconds). 0 inherits mssql_connection_timeout. Spec 047 FR-011.

Filter Pushdown Settings​

SettingTypeDefaultRangeDescription
mssql_scan_parameterize_filtersBOOLEANtrue-Send the constants of a pushed filter as sp_executesql parameters (an RPC call with typed values), declared from the column's SQL Server type, so SQL Server keeps one plan per filter shape instead of one per distinct value set. false restores literal SQL (the escape hatch for parameter sniffing).

Statistics Settings​

SettingTypeDefaultRangeDescription
mssql_enable_statisticsBOOLEANtrue-Enable statistics collection
mssql_statistics_levelBIGINT0≥0Detail: 0=rowcount, 1=+histogram, 2=+NDV
mssql_statistics_use_dbccBOOLEANfalse-Use DBCC SHOW_STATISTICS (requires permissions)
mssql_statistics_cache_ttl_secondsBIGINT300≥0Statistics cache TTL (seconds)

Wire Protocol Settings​

SettingTypeDefaultDescription
mssql_tds_packet_sizeBIGINT16384TDS frame size requested at login, clamped to [512, 32767]. Bounds recv() count on reads and send() count on bulk loads; raised from 4096 in v0.2.3 (−28% client CPU / −43% wall on read). Costs the server ~16 KB per pooled connection; set 4096 to restore the old footprint
mssql_utf8_supportBOOLEANtrueAdvertise TDS UTF8SUPPORT at login. A granting server sends UTF-8-collated columns without UTF-16 transcoding (measured half the wire bytes). Safe to request everywhere; exists to turn the request off. Without it a UTF-8 char(n) is read through CAST(… AS NCHAR(n)), so its padding is still trimmed
mssql_named_instance_resolutionBOOLEANtrueResolve Server=host\instance to the instance's dynamic port via SQL Server Browser (UDP 1434) at ATTACH. Set false where outbound UDP 1434 is stripped — a named instance then errors instead of silently using 1433
mssql_browser_timeout_secondsBIGINT3Browser UDP query timeout (ATTACH critical path; one retry)

Bulk Load (COPY / CTAS) Settings​

Details: COPY TO and CTAS.

SettingTypeDefaultDescription
mssql_copy_flush_rowsBIGINT102400Rows per bulk-load batch — the batch boundary the server sees, for COPY, CTAS and a bulk-path INSERT alike. 102 400 is SQL Server's own threshold for writing compressed columnstore rowgroups directly; smaller batches land in the delta store and never compress
mssql_copy_parallel_writersBIGINT0Concurrent bulk-load connections one COPY, CTAS or bulk-path INSERT may open. 0 derives from DuckDB threads (cap 8); 1 disables. Ignored inside explicit transactions (the load pins one connection). An INSERT fans out only on a target with no nonclustered index on it — a heap under TABLOCK, or a clustered columnstore without it. Its writers hold transactions, and conflicting locks would deadlock them: a heap carrying a nonclustered index takes a Sch-M lock under TABLOCK rather than the compatible BU lock, and a columnstore carrying one fails the load An INSERT's writers commit one after another: a reader under READ_COMMITTED_SNAPSHOT or SNAPSHOT can see part of one INSERT — 1 when it must not; a COPY / CTAS commits batch by batch whatever this says (details)
mssql_copy_tablockVARCHARautoauto | true | false. auto decides from the target's shape: heap ON, anything clustered OFF (the hint serialises parallel loaders against a clustered index). Applies to a bulk-path INSERT too
mssql_ctas_use_bcpBOOLEANtrueCTAS transfers data over the bulk-load protocol (2–10× the text INSERT path) and commits as it loads, DDL and rows. false: the CTAS runs whole inside the DuckDB transaction -- in autocommit the statement's own -- checks, CREATE and rows as INSERT statements on its one connection, and is committed or rolled back with it (issue #451)
mssql_ctas_text_typeVARCHARNVARCHARWhat an unannotated DuckDB VARCHAR becomes in created tables (NVARCHAR/VARCHAR); drives CTAS and COPY alike
mssql_ctas_drop_on_failureBOOLEANfalseDrop the created table when the load phase fails

Target Type Settings​

Details: Target Column Types and Table Shape.

SettingTypeDefaultDescription
mssql_utf8_collationVARCHARLatin1_General_100_BIN2_UTF8Collation for created varchar columns when the server granted UTF8SUPPORT. BIN2 = binary comparison, case-/accent-sensitive; matches Fabric's default. Empty inherits the database default
mssql_default_string_lengthBIGINT0Length for unannotated VARCHAR columns created by CTAS/COPY (0 = MAX)
mssql_default_table_kindVARCHARHEAPShape of created tables: HEAP or COLUMNSTORE (clustered columnstore index created before the load)
mssql_catalog_native_typesBOOLEANtrueReport MSSQL_VARCHAR(n) / MSSQL_NVARCHAR(n) for bounded string columns of attached tables and of mssql_scan / mssql_scan_params results (a varchar there only under a UTF-8 collation), so targets inherit declared lengths. Per catalog: the native_types ATTACH option.
mssql_convert_varchar_maxBOOLEANtrueConvert VARCHAR(MAX) to NVARCHAR(MAX) in catalog scan SQL for UTF-8 safety on non-UTF-8 collations

ORDER BY Pushdown Settings (Experimental)​

SettingTypeDefaultRangeDescription
mssql_order_pushdownBOOLEANfalse-Enable ORDER BY pushdown to SQL Server

The order_pushdown ATTACH option provides per-database control. See ORDER BY Pushdown for details.

Remote Pushdown Settings​

SettingTypeDefaultRangeDescription
mssql_remote_pushdownBOOLEANtrue-Send whole SELECT statements over one attached database to SQL Server as one T-SQL statement. Read at ATTACH and fixed for that database's life: set it before ATTACH, or give the database its own with the ATTACH option remote_pushdown true/false. Global (no per-session switch). While on, GROUP BY / DISTINCT / join keys / PARTITION BY compare strings under the column's collation — see Remote Pushdown. Also while on: the database's schema main answers as its default schema for reads and writes (db.main.t reads dbo.t; CREATE / DROP TABLE db.main.x act on dbo.x, where without it main is not found), DuckDB skips its catalog-or-schema ambiguity check for it, and DuckDB's pushdown rewriter runs on every statement of the instance
mssql_pushdown_join_rows_thresholdBIGINT1000000≥0A join whose gain is not certain (many-to-many, CROSS) is pushed only while every table it joins has fewer rows than this (cached counts, no round trip); else the table scans keep it; a view (no row count of its own) never counts as small. 0 = always push. Not checked inside a transaction or on a pool of one connection
mssql_pushdown_min_rowsBIGINT0≥0A statement whose tables hold fewer rows than this together (cached counts) is left to the table scans. The counts are the cached, approximate ones, and a table read twice (a self-join) counts twice. 0 = no floor. Not applied inside a transaction, on a pool of one connection, or when a view is read

INSERT Settings​

SettingTypeDefaultRangeDescription
mssql_insert_batch_sizeBIGINT1000≥1Rows per INSERT statement. Under it a cap of 1000 constants per statement always applies (1000 / columns rows), so SQL Server auto-parameterises every statement into one cached plan per shape
mssql_insert_max_rows_per_statementBIGINT1000≥1Hard cap on rows per INSERT
mssql_insert_max_sql_bytesBIGINT8388608≥1024Max SQL statement size (8MB)
mssql_insert_use_returning_outputBOOLEANtrue-Deprecated, no effect; removed in the next release (an INSERT … RETURNING always uses OUTPUT INSERTED, see INSERT with RETURNING)
mssql_insert_use_bcpBOOLEANtrue-Load an INSERT through the BCP protocol above mssql_insert_bcp_threshold rows, with parallel writers; in autocommit the INSERT commits on its own when it finishes. RETURNING and an explicit identity column always use statements. false: statements only, and in autocommit the INSERT joins the statement's DuckDB transaction -- committed or rolled back with it (issue #451)
mssql_insert_bcp_thresholdBIGINT1000≥1Rows up to which an INSERT is sent as statements; above it the bulk path. Counted as the rows arrive, not estimated

The bulk path takes its batch size, writer count and TABLOCK policy from the mssql_copy_* settings above, which describe a bulk load whatever statement started it. See INSERT.

UPDATE/DELETE Settings​

SettingTypeDefaultRangeDescription
mssql_dml_batch_sizeBIGINT500≥1Rows per UPDATE/DELETE batch
mssql_dml_max_parametersBIGINT2000≥1Max parameters per statement (~2100 limit)
mssql_dml_pushdownBOOLEANtrue—Send an UPDATE / DELETE / INSERT … SELECT / MERGE the remote-pushdown rewriter can write in T-SQL to SQL Server as one statement; false keeps every UPDATE / DELETE / INSERT … SELECT on the row paths and stages every MERGE through #src (it still runs on the server, or is refused by name). Read per statement
mssql_dml_stage_thresholdBIGINT1000≥0Rows up to which an UPDATE/DELETE on a keyed table goes as VALUES statements; past it, through a #stage table and one statement (0 = always stage)
mssql_dml_use_preparedBOOLEANtrue-Deprecated, no effect; removed in the next release

Usage Examples​

-- Increase connection pool for high-concurrency workloads
SET mssql_connection_limit = 20;

-- Reduce batch size for tables with large rows
SET mssql_insert_batch_size = 100;

-- Enable detailed statistics for query optimization
SET mssql_statistics_level = 2;

-- Disable connection caching for debugging
SET mssql_connection_cache = false;