Visitar URL original
Optimization: Can we use chunking for String ( CHAR,VARCAR,NVARCHAR) data type to remove extra memory allocation · Issue #455 · microsoft/mssql-python · GitHub
Skip to content

Optimization: Can we use chunking for String ( CHAR,VARCAR,NVARCHAR) data type to remove extra memory allocation #455

Description

@subrata-ms

Describe the bug

Currently we allocate fixed size memory ( coulumnsize+1) to handle string data type. This was causing problem for CP1252 character set. We have fix this issue under reported SQLAlchemy bug ( #435 ).
However, we do see an opportunity improve the memory allocation for the string data type. One of the consideration/approach could be chunking.
This will help to reduce unnecessary memory allocation considerably during multithreaded execution and for large dataset.

Exception message:
Stack trace:

To reproduce

This is considered as code optimization. Below is the related bug -
#435

Expected behavior

All string data type should handle CP1252 character set.

Activity

  1. github-actions commented on Feb 26, 2026

    @github-actions

    Hi Subrata (@subrata-ms), thank you for opening this issue!

    Our team will review it shortly. We aim to triage all new issues within 24-48 hours and get back to you.

    If you have additional information to share, please feel free to update the issue.

    Thank you for your patience!

  2. added
    triage doneIssues that are triaged by dev team and are in investigation.
    and removed
    triage doneIssues that are triaged by dev team and are in investigation.
    triage neededFor new issues, not triaged yet.
    on Apr 6, 2026
  3. Digma commented on Apr 27, 2026

    @Digma

    We are facing the same issue. We are trying to load some unbounded VARCHAR columns and using mssql, it requires a huge amount of pre-allocated memory which is much larger than the actual memory required to load the column.

    Unfortunately, we do not control the data schema so optimizing the column type is not an option. Optimizing the memory requirements would be a huge improvement to the library for us.

  4. added
    enhancementNew feature or request
    and removed
    bugSomething isn't working
    on Jun 1, 2026
  5. added
    area: performanceThroughput, latency, GIL retention, large-param slowness, expensive round-trips, perf-regressions
    on Jun 4, 2026
  6. jonahmdot commented on Oct 8, 2026

    @jonahmdot

    I ran into this issue while fetching results from a SQL Server view containing several VARCHAR(8000) columns. These columns were generated by STRING_AGG, which commonly produces VARCHAR(8000) metadata when aggregating VARCHAR(n) values, even when the actual strings are very short.

    I compared mssql-python against pyodbc using the same view and fetchall(). Despite returning identical results, mssql-python consistently used nearly 2x the peak memory of pyodbc, with slightly slower fetch times.

    After looking through ddbc_bindings.cpp, I noticed a few additional issues that seem to amplify the allocation problem described here:

    1. Eager allocation for 1,000 rows: FetchAll_wrap defaults to a fetchSize of 1,000 for smaller estimated row sizes, allocating buffers before knowing how many rows the query actually returns. Even a query returning only a handful of rows can therefore allocate buffers for 1,000 rows.

    2. 1 GiB memory budget: The memoryLimit used to calculate fetchSize is set to 1 GiB. This seems quite large for a single cursor, particularly in applications executing multiple concurrent queries. It also appears to be a sizing heuristic rather than a strict memory limit, since the estimated row size doesn't necessarily reflect the actual allocated buffer sizes.

    3. Allocation based on declared rather than actual lengths: This is particularly problematic for STRING_AGG columns. A column declared as VARCHAR(8000) might contain only a few characters, but the driver still allocates space based on the full declared width for every row in the fetch batch.

    It might be worth looking at how other SQL Server drivers handle this. For example, go-mssqldb uses reusable per-column buffers for variable-length types and reads values based on their actual lengths, rather than preallocating a full-width buffer for every row. pyodbc also uses SQLGetData for variable-length data, which might be a more directly applicable reference given that both libraries use ODBC.

    I realize that changing the buffer allocation strategy may involve some tradeoffs with batched fetching, but I wonder whether a combination of smaller initial batches, a substantially lower default memory budget, and dynamically sized or reusable buffers could help.

    Even independently of the string-buffer optimization proposed in this issue, adjusting the default fetchSize and memoryLimit behavior seems worthwhile to prevent excessive memory usage for small result sets.

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

Metadata

Metadata

Labels

area: performanceThroughput, latency, GIL retention, large-param slowness, expensive round-trips, perf-regressionsenhancementNew feature or requesttriage doneIssues that are triaged by dev team and are in investigation.

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions