cursor.execute() with many bound parameters (~2000) is ~14x slower than pyodbc
Mantenedores costumam responder em até 2 dias
@bewithgaurav já está trabalhando nisso.
Desde 9/4/2026.
Avaliação
Esta issue ainda não foi avaliada.
Descrição
Describe the bug
When executing a multi-row INSERT with ~2000 bound parameters (the kind SQLAlchemy's insertmanyvalues generates), cursor.execute() is about 14x slower than the equivalent call through pyodbc.
cursor.executemany() is much closer between drivers (~1.6x), so the issue is specific to single cursor.execute() calls with large parameter counts.
To reproduce
import time
import mssql_python
import pyodbc
N = 100_000
COLS = 2
# ~1049 rows per INSERT, ~2098 params per call, ~95 calls total
ROWS_PER_BATCH = 2099 // COLS
SQL = "INSERT INTO bench (id, name) VALUES " + ",".join(
[f"(?, ?)"] * ROWS_PER_BATCH
)
PARAMS = [None] * (ROWS_PER_BATCH * COLS)
# --- mssql-python ---
conn = mssql_python.connect(
"SERVER=localhost;DATABASE=master;UID=sa;PWD=YourPassword;"
"Encrypt=yes;TrustServerCertificate=yes;"
)
cursor = conn.cursor()
cursor.execute(
"IF OBJECT_ID('bench') IS NOT NULL DROP TABLE bench;"
"CREATE TABLE bench (id INT, name VARCHAR(50))"
)
conn.commit()
t0 = time.perf_counter()
for _ in range(N // ROWS_PER_BATCH):
cursor.execute(SQL, PARAMS)
conn.commit()
ms_time = time.perf_counter() - t0
cursor.close()
conn.close()
# --- pyodbc ---
conn2 = pyodbc.connect(
"DRIVER={ODBC Driver 18 for SQL Server};"
"SERVER=localhost;DATABASE=master;UID=sa;PWD=YourPassword;"
"Encrypt=yes;TrustServerCertificate=yes;"
)
cursor2 = conn2.cursor()
cursor2.execute("TRUNCATE TABLE bench")
conn2.commit()
t0 = time.perf_counter()
for _ in range(N // ROWS_PER_BATCH):
cursor2.execute(SQL, PARAMS)
conn2.commit()
py_time = time.perf_counter() - t0
cursor2.close()
conn2.close()
print(f"mssql-python: {ms_time:.2f}s ({N / ms_time:,.0f} rows/s)")
print(f"pyodbc: {py_time:.2f}s ({N / py_time:,.0f} rows/s)")
Output
mssql-python: 11.87s (8,427 rows/s)
pyodbc: 0.77s (130,000 rows/s)
Context
This came up while working on SQLAlchemy integration. SA 2.x uses insertmanyvalues by default, which generates batched multi-row INSERTs with ~2098 parameters per call (limited by SQL Server's 2100 parameter cap).
For reference, cursor.executemany() is much faster on this driver (~50K rows/s) and cursor.bulkcopy() is excellent (~390K rows/s). It's really just the many-parameter cursor.execute() path that's slow.
Environment
- mssql-python: 1.4.0
- pyodbc: 5.2.0
- SQL Server: 2022
- Python: 3.12
- OS: Ubuntu 24.04
- Linguagem predominante
- Python
- Estrelas
- 478
- Forks
- 62
- Merge médio
- 3d 19min
- PRs com merge (30d)
- 28
Preparar o ambiente
Inicia o contêiner de desenvolvimento do projeto no navegador, com a sua própria conta do GitHub.
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de microsoft/mssql-python
-
area: bulk-copy triage needed
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
microsoft/mssql-python#843 · 1 comentário ·
Mantenedores costumam responder em até 2 dias
-
triage needed
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 35/100
microsoft/mssql-python#846 · 1 comentário ·
Mantenedores costumam responder em até 2 dias
-
macOS: encrypted connections fail after Homebrew moved the `openssl` alias to `openssl@4`Talvez já em andamento @bewithgaurav assumiu há 14 dias. Abertaarea: packaging-platform bug triage needed
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 55/100
microsoft/mssql-python#826 · 2 comentários · 1 responsável ·
Mantenedores costumam responder em até 2 dias
-
Announcement: mssql-python is coming to Django through mssql-django 2.0Talvez livre de novo @bewithgaurav assumiu há 41 dias e não há nenhum pull request aberto. Abertaannouncement
microsoft/mssql-python#748 · 1 responsável ·
Mantenedores costumam responder em até 2 dias
-
Connection pool can briefly exceed max_size when pooling is disabled under loadTalvez já em andamento @bewithgaurav assumiu há 23 dias. Abertaarea: connectivity-auth bug triage done under development
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 62/100
microsoft/mssql-python#746 · 1 comentário · 1 responsável ·
Mantenedores costumam responder em até 2 dias
Todas as issues de microsoft/mssql-python
Issues semelhantes
-
good first issue
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 85/100
btclib-org/btclib-node#1955 ·
Mantenedores costumam responder em até 1 dia
-
documentation v0.9.2
Dificuldade 2/5 Meio dia Facilidade para iniciantes 72/100
khuisman/mcp-gee-sweet#1033 ·
Mantenedores costumam responder em até 1 dia
-
bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
ossf/cve-bin-tool#5966 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
Mantenedores costumam responder em até 2 dias
-
write_iceberg ignores the table's write.parquet.compression-codec propertyTalvez já em andamento @YuangGao assumiu hoje. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
Eventual-Inc/Daft#7606 ·
Mantenedores costumam responder em até 1 dia