Skip to content

PERF: Cache full column counts for fetchone - #829

Draft
Jahnvi Thakkar (jahnvi480) wants to merge 4 commits into
mainfrom
jahnvi/candidate-a-fetchone-column-count
Draft

Jahnvi Thakkar (jahnvi480) wants to merge 4 commits into
mainfrom
jahnvi/candidate-a-fetchone-column-count

Conversation

@jahnvi480

@jahnvi480 Jahnvi Thakkar (jahnvi480) commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Work Item / Issue Reference

AB#48364


Summary

Draft Candidate A experiment for evaluation with the existing CI performance report; not ready to merge and no measured speedup claimed.

  • Reuse the full result column count in native FetchOne_wrap within the existing statement metadata generation, instead of querying it after every successful row fetch.
  • Keep full cardinality separate from partial SQLGetData metadata; publish only for the matching generation and reset on existing invalidation.
  • Preserve unbinding, diagnostics, error handling, Python APIs and uncached explicit column-count calls.
  • Add nine subprocess-isolated native scenarios covering reuse, partial metadata, changed shapes, nextset, fetch/count/decode failures, generation changes and mixed fetch APIs.

Both fresh Linux x86_64 CPython 3.13 Release/profiling-OFF builds and imports succeeded. Local correctness execution and timing remain unrun because the required SQL-side FD inspection was permission-denied. The new tests and performance effect still require validation.

The CI report will be assessed per workload, including unchanged-path regressions. Profiling-enabled attribution will not be presented as a measured shipped Release-OFF speedup.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 1, 2026 09:00
@github-actions github-actions Bot added the pr-size: medium Moderate update size label Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

PR Performance Report

✅ No regression detected

No consistent slowdowns detected across all 2 environments.

0 IMPROVEMENTS 0 SLOWDOWNS 2/2 ENVIRONMENTS

Coverage: 2 of 2 environments completed. Advisory result; does not block merging.

Performance diagnostics

Phase times are inclusive diagnostics and must not be added together. They identify where measured time changed, not why it changed.

Unix / SQL Server 2022

Row-by-row fetching: py::fetchone::row_wrap +0.034 ms; ddbc::SQLDescribeCol::driver_call +0.000 ms. Call changes: ddbc::SQLNumResultCols_wrap (1000 -> 1 calls).
10,000 scalar values / fetchval() (debug disabled): ddbc::SQLGetData_wrap +0.079 ms. Call changes: ddbc::SQLNumResultCols_wrap (10000 -> 1 calls).

Unix / SQL Server 2025

Row-by-row fetching: py::fetchone::row_wrap +0.016 ms; ddbc::SQLGetData_wrap +0.007 ms; ddbc::AppendDiagRecords::SQLGetDiagRec_call +0.003 ms. Call changes: ddbc::SQLNumResultCols_wrap (1000 -> 1 calls).
10,000 scalar values / fetchval() (debug disabled): ddbc::SQLGetData_wrap +0.334 ms; py::fetchone::row_wrap +0.066 ms; ddbc::AppendDiagRecords::SQLGetDiagRec_call +0.000 ms. Call changes: ddbc::SQLNumResultCols_wrap (10000 -> 1 calls).

All database tasks and timings

Unix / SQL Server 2022

Database task Before After Paired change Result
Connection opening 10.309 ms 10.413 ms +2.0% no signal
SELECT queries 1.098 ms 1.055 ms -3.3% no signal
Row insertion 35.160 ms 34.467 ms -1.4% no signal
Executemany inserts 156.732 ms 156.754 ms +1.5% no signal
Fetch-all queries 120.595 ms 120.348 ms -0.3% no signal
Row-by-row fetching 14.051 ms 14.075 ms +0.2% no signal
Batched row fetching 116.737 ms 116.596 ms +0.1% no signal
Transaction commit and rollback 112.658 ms 113.277 ms +1.4% no signal
Arrow row fetching 94.861 ms 94.505 ms -0.5% no signal
100,000-row insertion 439.384 ms 445.241 ms +1.6% no signal
Row fetching in batches of 100 122.451 ms 123.070 ms -1.3% no signal
Row fetching in batches of 10,000 124.226 ms 137.868 ms +11.5% no signal
Repeated positional queries 33.637 ms 33.439 ms -2.3% no signal
Repeated named-parameter queries 35.584 ms 35.927 ms -0.1% no signal
Legacy 100,000-row insertion 350.186 ms 389.191 ms -1.3% no signal
Insertion with explicit input sizes 484.158 ms 494.597 ms -0.0% no signal
Joined aggregation queries 178.794 ms 181.416 ms +1.0% no signal
Large joined-result fetching 179.716 ms 180.623 ms +1.4% no signal
1.2-million-row fetching 3452.925 ms 3458.213 ms +0.1% no signal
Common table expression queries 5.274 ms 5.324 ms +1.0% no signal
256 KiB VARCHAR(MAX) / fetchall() 1.221 ms 1.365 ms +7.6% no signal
10,000 scalar values / fetchval() (debug disabled) 107.829 ms 105.424 ms -1.9% no signal

Unix / SQL Server 2025

Database task Before After Paired change Result
Connection opening 97.955 ms 97.438 ms +0.4% no signal
SELECT queries 1.104 ms 1.151 ms +3.1% no signal
Row insertion 34.797 ms 35.334 ms +0.4% no signal
Executemany inserts 152.765 ms 154.248 ms +1.3% no signal
Fetch-all queries 121.483 ms 122.086 ms +0.3% no signal
Row-by-row fetching 14.476 ms 14.459 ms -1.2% no signal
Batched row fetching 117.490 ms 118.582 ms +1.4% no signal
Transaction commit and rollback 117.538 ms 116.765 ms +0.1% no signal
Arrow row fetching 95.842 ms 96.771 ms +1.1% no signal
100,000-row insertion 447.938 ms 504.055 ms +4.3% no signal
Row fetching in batches of 100 122.956 ms 123.974 ms +0.1% no signal
Row fetching in batches of 10,000 141.170 ms 144.595 ms -1.1% no signal
Repeated positional queries 34.875 ms 34.614 ms -0.7% no signal
Repeated named-parameter queries 37.208 ms 36.737 ms -1.3% no signal
Legacy 100,000-row insertion 361.137 ms 358.843 ms -2.1% no signal
Insertion with explicit input sizes 504.052 ms 501.222 ms -0.8% no signal
Joined aggregation queries 165.359 ms 161.283 ms -1.4% no signal
Large joined-result fetching 194.120 ms 191.721 ms -1.6% no signal
1.2-million-row fetching 3556.723 ms 3583.845 ms +1.3% no signal
Common table expression queries 5.330 ms 5.479 ms +2.4% no signal
256 KiB VARCHAR(MAX) / fetchall() 1.548 ms 1.537 ms -3.5% no signal
10,000 scalar values / fetchval() (debug disabled) 108.290 ms 106.318 ms -1.4% no signal
Build and measurement details

ADO build 180433

PR head: 492dd7ada4b63a0f021adb2580d825b0ad9563b3
Base: 436b6cbc94092eee59c803d2acf3bcaf8c21aa0f
Measured merge: 650d93e1270345119e36705cf5c6035131ac6fd7

  • Unix / SQL Server 2022: Python 3.12.3, x86_64, SQL 16.0.4295.3; 5 paired comparisons and 1 warmup.
  • Unix / SQL Server 2025: Python 3.12.3, x86_64, SQL 17.0.5005.3; 5 paired comparisons and 1 warmup.

A consistent change requires more than 20% median paired movement, at least 1 ms between the median runtimes, and at least 80% of pairs exceeding the relative threshold in the same direction. A slowdown without enough pair agreement is reported as inconsistent.

The displayed change is the median of paired before-and-after ratios. It is not recalculated from the two displayed median runtimes.

Both revisions use profiling-enabled builds on the same agent and database, with alternating order and discarded warmups. Results are diagnostic and do not represent production-wheel latency.

Raw samples and logs are attached to the ADO run as profiler-* artifacts.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The native hot-path change still requires live correctness and performance validation, as acknowledged by the draft description.

Review effort: Balanced
Findings: None

What changed in this PR

Introduces an experimental native cache to avoid repeated column-count queries during fetchone.

Changes:

  • Caches full column counts by metadata generation.
  • Reuses cached counts while preserving invalidation and error handling.
  • Adds nine subprocess-isolated integration scenarios.
File Description
mssql_python/​pybind/​ddbc_bindings.cpp Uses the cached count in FetchOne_wrap.
mssql_python/​pybind/​result_metadata.hpp Stores and invalidates full column counts.
tests/​test_fetch_settings_cache.py Tests reuse, invalidation, failures, and mixed fetching.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Use a separate connection for the cross-handle assertion without requiring MARS. Preserve all fetch and native call-count assertions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 1, 2026 10:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The native hot-path change remains an explicitly unvalidated draft with correctness tests and performance measurements still pending.

Review effort: Balanced
Findings: None

Copilot AI balanced review requested due to automatic review settings October 1, 2026 10:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The native cache behavior and performance impact remain unvalidated by runtime execution.

Review effort: Balanced
Findings: None

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

📊 Code Coverage Report

🔥 Diff Coverage

100%


🎯 Overall Coverage

84%


📈 Total Lines Covered: 9430 out of 11101
📁 Project: mssql-python


Diff Coverage

Diff: main...HEAD, staged and unstaged changes

  • mssql_python/pybind/result_metadata.hpp (100%)

Summary

  • Total: 8 lines
  • Missing: 0 lines
  • Coverage: 100%

📋 Files Needing Attention

📉 Files with overall lowest coverage (click to expand)
mssql_python.pybind.performance_counter.hpp: 0.7%
mssql_python.pybind.logger_bridge.cpp: 57.9%
mssql_python.pybind.ddbc_bindings.h: 62.6%
mssql_python.pybind.logger_bridge.hpp: 70.8%
mssql_python.pybind.ddbc_bindings.cpp: 79.5%
mssql_python.pybind.connection.connection_pool.cpp: 82.3%
mssql_python.pybind.connection.connection.cpp: 83.1%
mssql_python.logging.py: 86.2%
mssql_python.pooling.py: 90.1%
mssql_python.pybind.fetch_temporal.hpp: 92.1%

🔗 Quick Links

⚙️ Build Summary 📋 Coverage Details

View Azure DevOps Build

Browse Full Coverage Report

Copilot AI balanced review requested due to automatic review settings October 5, 2026 06:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Native correctness tests and uninstrumented Release performance measurements remain unrun.

Review effort: Balanced
Findings: None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-size: medium Moderate update size

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants