fastmssql 0.2.4__cp310-cp310-macosx_11_0_arm64.whl → 0.2.7__cp310-cp310-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fastmssql might be problematic. Click here for more details.
- fastmssql/__init__.py +654 -11
- fastmssql/fastmssql.cpython-310-darwin.so +0 -0
- {fastmssql-0.2.4.dist-info → fastmssql-0.2.7.dist-info}/METADATA +85 -217
- fastmssql-0.2.7.dist-info/RECORD +6 -0
- fastmssql/fastmssql.py +0 -706
- fastmssql/fastmssql_core.cpython-310-darwin.so +0 -0
- fastmssql-0.2.4.dist-info/RECORD +0 -7
- {fastmssql-0.2.4.dist-info → fastmssql-0.2.7.dist-info}/WHEEL +0 -0
- {fastmssql-0.2.4.dist-info → fastmssql-0.2.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmssql
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: Other/Proprietary License
|
|
@@ -29,59 +29,57 @@ Project-URL: Homepage, https://github.com/Rivendael/pymssql-rs
|
|
|
29
29
|
|
|
30
30
|
# Fastmssql ⚡
|
|
31
31
|
|
|
32
|
-
A
|
|
32
|
+
A Python library for Microsoft SQL Server built with Rust using the [Tiberius](https://github.com/prisma/tiberius) driver, [PyO3](https://github.com/PyO3/pyo3), and [bb8](https://github.com/djc/bb8) connection pooling.
|
|
33
33
|
|
|
34
|
-
> **🚀 Performance Highlight**: Achieves **3,493 requests/second** and **0.08 KB memory per query** in our benchmarks
|
|
35
|
-
|
|
36
|
-
[](https://github.com/Rivendael/pymssql-rs)
|
|
37
|
-
[](https://github.com/Rivendael/pymssql-rs)
|
|
38
|
-
[](https://github.com/Rivendael/pymssql-rs)
|
|
39
34
|
[](https://github.com/Rivendael/pymssql-rs)
|
|
40
35
|
[](https://github.com/Rivendael/pymssql-rs)
|
|
36
|
+
[](https://github.com/Rivendael/pymssql-rs)
|
|
41
37
|
|
|
42
38
|
## Features
|
|
43
39
|
|
|
44
|
-
- **High Performance**:
|
|
40
|
+
- **High Performance**: Exceptional throughput with 17,800+ RPS capability
|
|
41
|
+
- **Rust-Powered Backend**: Built with Rust for memory safety and reliability
|
|
45
42
|
- **No ODBC Required**: Direct native SQL Server connection without ODBC drivers
|
|
46
|
-
- **Connection Pooling**:
|
|
47
|
-
- **Async-Only Design**: Built on Tokio
|
|
43
|
+
- **Connection Pooling**: Intelligent bb8-based connection pooling (default: 75 max, 25 min idle)
|
|
44
|
+
- **Async-Only Design**: Built on Tokio with clean async/await API
|
|
48
45
|
- **Context Managers**: Automatic resource management with `async with`
|
|
49
46
|
- **Type Safety**: Strong typing with automatic Python type conversion
|
|
50
|
-
- **Thread Safety**:
|
|
47
|
+
- **Thread Safety**: Support for concurrent operations
|
|
51
48
|
- **Cross-Platform**: Works on Windows, macOS, and Linux
|
|
52
49
|
- **Simple API**: Clean, intuitive async-only interface
|
|
53
50
|
|
|
54
|
-
##
|
|
55
|
-
|
|
56
|
-
Fastmssql delivers **excellent performance** that outperforms standard Python SQL Server libraries in our testing:
|
|
57
|
-
|
|
58
|
-
### 🚀 Benchmark Results
|
|
51
|
+
## Performance Highlights
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
|---------|----------------------|--------------------------|
|
|
62
|
-
| **fastmssql** | **3,493** | **Baseline** |
|
|
63
|
-
| Other Python libraries | ~300-600* | **5-11x slower** |
|
|
53
|
+
Fastmssql delivers exceptional database performance through Rust-powered architecture:
|
|
64
54
|
|
|
65
|
-
|
|
55
|
+
- **Outstanding Throughput**: Up to **17,800+ RPS** with multiple connection pattern
|
|
56
|
+
- **High Performance**: **5,000+ RPS** with single connection (default usage)
|
|
57
|
+
- **Low Latency**: ~2ms average query latency under high load
|
|
58
|
+
- **Scalable Architecture**: Linear scaling with multiple connection objects
|
|
59
|
+
- **Production Ready**: Stable API with comprehensive error handling
|
|
60
|
+
- **Connection Pooling**: Efficient resource management with configurable pools
|
|
61
|
+
- **Type Conversion**: Automatic conversion between SQL Server and Python types
|
|
62
|
+
- **SSL/TLS Support**: Secure connections with flexible encryption options
|
|
66
63
|
|
|
67
|
-
###
|
|
64
|
+
### Performance Benchmarks
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
| Pattern | RPS | Configuration | Use Case |
|
|
67
|
+
|---------|-----|---------------|----------|
|
|
68
|
+
| Single Connection (Default) | **5,000+** | Default pool (75/25) | Standard applications |
|
|
69
|
+
| Multiple Connections | **17,800+** | 50 workers, high_throughput() | High-concurrency scenarios |
|
|
70
|
+
| Conservative Load | 3,500+ | Shared connection | Traditional pooling |
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
| **Memory Leaks** | **None** | Actually reduces memory over time |
|
|
72
|
+
**Benchmark Environment:**
|
|
73
|
+
- Database: SQL Server (local instance)
|
|
74
|
+
- Query: `SELECT 1` (minimal overhead)
|
|
75
|
+
- Test Duration: 15-30 seconds per test
|
|
76
|
+
- Hardware: Modern development machine
|
|
77
77
|
|
|
78
|
-
**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
*Traditional Python SQL Server libraries typically use 50-200 KB per operation due to connection overhead and lack of efficient pooling.*
|
|
78
|
+
**Key Performance Insights:**
|
|
79
|
+
1. **Multiple Connection Objects**: Creating separate `Connection()` objects eliminates serialization bottlenecks
|
|
80
|
+
2. **Pool Configuration**: Use `PoolConfig.high_throughput()` for demanding workloads
|
|
81
|
+
3. **Optimal Worker Count**: 30-50 concurrent workers provides best throughput
|
|
82
|
+
4. **Tokio Optimization**: Aggressive threading configuration maximizes async performance
|
|
85
83
|
|
|
86
84
|
## Installation
|
|
87
85
|
|
|
@@ -115,8 +113,6 @@ cd mssql-python-rust
|
|
|
115
113
|
|
|
116
114
|
## Quick Start
|
|
117
115
|
|
|
118
|
-
> **💡 Performance Tip**: Always reuse `Connection` objects! Each `Connection` manages a connection pool, so creating multiple `Connection` instances defeats the purpose of pooling and hurts performance. Create one `Connection` per database and reuse it throughout your application.
|
|
119
|
-
|
|
120
116
|
### Basic Async Usage (Recommended)
|
|
121
117
|
|
|
122
118
|
```python
|
|
@@ -185,6 +181,40 @@ async def main():
|
|
|
185
181
|
asyncio.run(main())
|
|
186
182
|
```
|
|
187
183
|
|
|
184
|
+
### Performance Patterns
|
|
185
|
+
|
|
186
|
+
For maximum performance in high-concurrency scenarios, create multiple Connection objects:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
import asyncio
|
|
190
|
+
from fastmssql import Connection, PoolConfig
|
|
191
|
+
|
|
192
|
+
async def high_performance_pattern():
|
|
193
|
+
"""Optimal pattern for maximum throughput."""
|
|
194
|
+
connection_string = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
|
|
195
|
+
config = PoolConfig.high_throughput() # Optimized settings
|
|
196
|
+
|
|
197
|
+
async def worker():
|
|
198
|
+
# Each worker gets its own Connection object for maximum throughput
|
|
199
|
+
async with Connection(connection_string, pool_config=config) as conn:
|
|
200
|
+
for _ in range(1000):
|
|
201
|
+
# Use proper SQL Server parameterization with @param syntax
|
|
202
|
+
result = await conn.execute("SELECT data FROM my_table WHERE id = @id", {"id": 123})
|
|
203
|
+
# Process results...
|
|
204
|
+
|
|
205
|
+
# Launch multiple workers - each with their own connection
|
|
206
|
+
workers = [asyncio.create_task(worker()) for _ in range(50)]
|
|
207
|
+
await asyncio.gather(*workers)
|
|
208
|
+
|
|
209
|
+
# This pattern can achieve 17,800+ RPS
|
|
210
|
+
|
|
211
|
+
asyncio.run(high_performance_pattern())
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Key Performance Insight**: While a single Connection object provides excellent performance (5,000+ RPS),
|
|
215
|
+
creating multiple Connection objects eliminates serialization bottlenecks and can achieve 17,800+ RPS
|
|
216
|
+
for maximum throughput scenarios.
|
|
217
|
+
|
|
188
218
|
### Connection Pool Configuration
|
|
189
219
|
|
|
190
220
|
Configure the connection pool for your specific needs:
|
|
@@ -206,95 +236,29 @@ async def main():
|
|
|
206
236
|
async with Connection(connection_string, pool_config) as conn:
|
|
207
237
|
result = await conn.execute("SELECT * FROM users")
|
|
208
238
|
|
|
209
|
-
# Predefined configurations for
|
|
210
|
-
high_throughput_config = PoolConfig.high_throughput()
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
### 🔥 Maximum Performance Configuration
|
|
218
|
-
|
|
219
|
-
For applications requiring **extreme performance**, use the high-throughput configuration:
|
|
220
|
-
|
|
221
|
-
```python
|
|
222
|
-
import asyncio
|
|
223
|
-
from fastmssql import Connection, PoolConfig
|
|
224
|
-
|
|
225
|
-
async def main():
|
|
226
|
-
# Maximum performance setup
|
|
227
|
-
extreme_config = PoolConfig.high_throughput() # Optimized for 3000+ RPS
|
|
239
|
+
# Predefined configurations for different scenarios
|
|
240
|
+
high_throughput_config = PoolConfig.high_throughput() # 100 connections, optimized for high RPS
|
|
241
|
+
maximum_performance = PoolConfig.maximum_performance() # 150 connections, optimized for peak load
|
|
242
|
+
low_resource_config = PoolConfig.low_resource() # 3 connections, minimal resources
|
|
243
|
+
dev_config = PoolConfig.development() # 5 connections, shorter timeouts
|
|
244
|
+
|
|
245
|
+
# Default configuration is optimized for high performance
|
|
246
|
+
# Default: max_size=75, min_idle=25 - ready for production workloads
|
|
228
247
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
async def worker():
|
|
234
|
-
result = await conn.execute("SELECT @@VERSION")
|
|
248
|
+
# For maximum throughput, use multiple Connection objects:
|
|
249
|
+
async def high_perf_worker():
|
|
250
|
+
async with Connection(connection_string, maximum_performance) as conn:
|
|
251
|
+
result = await conn.execute("SELECT * FROM fast_table")
|
|
235
252
|
return result.rows()
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
# Pool monitoring
|
|
242
|
-
stats = await conn.pool_stats()
|
|
243
|
-
print(f"Pool utilization: {stats['active_connections']}/{stats['max_size']}")
|
|
253
|
+
|
|
254
|
+
# Each worker gets its own connection for optimal performance
|
|
255
|
+
tasks = [asyncio.create_task(high_perf_worker()) for _ in range(50)]
|
|
256
|
+
results = await asyncio.gather(*tasks)
|
|
244
257
|
|
|
245
258
|
asyncio.run(main())
|
|
246
259
|
```
|
|
247
260
|
|
|
248
|
-
**Performance Tips:**
|
|
249
|
-
- **Reuse Connection objects**: Create one `Connection` per database and reuse it across your application
|
|
250
|
-
- Use `PoolConfig.high_throughput()` for maximum RPS
|
|
251
|
-
- Leverage `asyncio.gather()` for concurrent operations
|
|
252
|
-
- Monitor pool stats to optimize connection count
|
|
253
|
-
- Consider connection lifetime for long-running applications
|
|
254
261
|
|
|
255
|
-
**⚠️ Performance Anti-Pattern:**
|
|
256
|
-
```python
|
|
257
|
-
# DON'T DO THIS - Creates new pool for each operation
|
|
258
|
-
async def bad_example():
|
|
259
|
-
async with Connection(conn_str) as conn: # New pool created
|
|
260
|
-
return await conn.execute("SELECT 1")
|
|
261
|
-
|
|
262
|
-
async with Connection(conn_str) as conn: # Another new pool created
|
|
263
|
-
return await conn.execute("SELECT 2")
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
**✅ Correct Pattern:**
|
|
267
|
-
```python
|
|
268
|
-
# DO THIS - Reuse the same connection pool
|
|
269
|
-
async def good_example():
|
|
270
|
-
async with Connection(conn_str) as conn: # Single pool created
|
|
271
|
-
result1 = await conn.execute("SELECT 1")
|
|
272
|
-
result2 = await conn.execute("SELECT 2") # Reuses same pool
|
|
273
|
-
return result1, result2
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Connection Pool Benefits
|
|
277
|
-
|
|
278
|
-
The bb8 connection pool provides significant performance improvements over traditional Python libraries:
|
|
279
|
-
|
|
280
|
-
| Metric | Traditional Python | fastmssql | Improvement |
|
|
281
|
-
|--------|-------------------|-----------|-------------|
|
|
282
|
-
| **Connection Setup** | 50ms | 0.1ms | **500x faster** |
|
|
283
|
-
| **Memory per Query** | 50-200 KB | 0.08 KB | **625-2500x less** |
|
|
284
|
-
| **10 Concurrent Queries** | 500ms | 150ms | **3.3x faster** |
|
|
285
|
-
| **100 Concurrent Queries** | 5000ms | 400ms | **12.5x faster** |
|
|
286
|
-
| **1000 Concurrent Queries** | Timeouts/Errors | 2.9s | **Stable** |
|
|
287
|
-
| **Memory Leaks** | Common | None | **Zero leaks** |
|
|
288
|
-
|
|
289
|
-
**Key Benefits:**
|
|
290
|
-
- **Connection Reuse**: Eliminates connection establishment overhead (500x improvement)
|
|
291
|
-
- **Memory Efficiency**: Uses 625-2500x less memory per operation (0.08 KB vs 50-200 KB)
|
|
292
|
-
- **Zero Memory Leaks**: Automatic cleanup with decreasing memory usage over time
|
|
293
|
-
- **Concurrency**: Safe multi-threaded access with automatic pooling
|
|
294
|
-
- **Resource Management**: Intelligent memory and connection lifecycle management
|
|
295
|
-
- **Load Balancing**: Intelligent connection distribution across threads
|
|
296
|
-
- **Fault Tolerance**: Built-in retry logic and connection health checks
|
|
297
|
-
- **Timeouts**: Configurable timeouts prevent hanging connections
|
|
298
262
|
|
|
299
263
|
### Connection Strings
|
|
300
264
|
|
|
@@ -390,89 +354,6 @@ async def main():
|
|
|
390
354
|
asyncio.run(main())
|
|
391
355
|
```
|
|
392
356
|
|
|
393
|
-
### Performance Comparison: bb8 Connection Pool
|
|
394
|
-
|
|
395
|
-
The bb8 connection pool dramatically improves performance, especially under load:
|
|
396
|
-
|
|
397
|
-
```python
|
|
398
|
-
import asyncio
|
|
399
|
-
import time
|
|
400
|
-
from fastmssql import Connection
|
|
401
|
-
|
|
402
|
-
async def performance_comparison():
|
|
403
|
-
connection_string = "Server=localhost;Database=test;User Id=myuser;Password=mypass"
|
|
404
|
-
|
|
405
|
-
# Sequential async operations (still efficient with pool reuse)
|
|
406
|
-
start = time.time()
|
|
407
|
-
async with Connection(connection_string) as conn:
|
|
408
|
-
for i in range(10):
|
|
409
|
-
result = await conn.execute("SELECT COUNT(*) FROM users")
|
|
410
|
-
sequential_time = time.time() - start
|
|
411
|
-
|
|
412
|
-
# Concurrent async operations (much faster with bb8 pool)
|
|
413
|
-
start = time.time()
|
|
414
|
-
async def concurrent_queries():
|
|
415
|
-
tasks = []
|
|
416
|
-
for i in range(10):
|
|
417
|
-
async def query():
|
|
418
|
-
async with Connection(connection_string) as conn: # Pool reuse
|
|
419
|
-
return await conn.execute("SELECT COUNT(*) FROM users")
|
|
420
|
-
tasks.append(query())
|
|
421
|
-
return await asyncio.gather(*tasks)
|
|
422
|
-
|
|
423
|
-
await concurrent_queries()
|
|
424
|
-
concurrent_time = time.time() - start
|
|
425
|
-
|
|
426
|
-
print(f"Sequential: {sequential_time:.3f}s")
|
|
427
|
-
print(f"Concurrent: {concurrent_time:.3f}s")
|
|
428
|
-
print(f"Improvement: {sequential_time/concurrent_time:.1f}x faster")
|
|
429
|
-
|
|
430
|
-
asyncio.run(performance_comparison())
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
**Real-world Performance Benefits:**
|
|
434
|
-
- **Web Applications**: Handle 100+ concurrent requests without connection exhaustion
|
|
435
|
-
- **Batch Processing**: Process large datasets with optimal resource usage
|
|
436
|
-
- **Microservices**: Reliable database connections across service boundaries
|
|
437
|
-
- **Data Analytics**: Concurrent query execution for faster insights
|
|
438
|
-
|
|
439
|
-
## Examples
|
|
440
|
-
|
|
441
|
-
Run the provided examples to see async patterns and features:
|
|
442
|
-
|
|
443
|
-
```bash
|
|
444
|
-
# Basic asynchronous usage
|
|
445
|
-
python examples/basic_usage.py
|
|
446
|
-
|
|
447
|
-
# Advanced asynchronous features
|
|
448
|
-
python examples/advanced_usage.py
|
|
449
|
-
|
|
450
|
-
# Asynchronous usage patterns
|
|
451
|
-
python examples/async_usage.py
|
|
452
|
-
|
|
453
|
-
# Advanced pool configuration
|
|
454
|
-
python examples/advanced_pool_config.py
|
|
455
|
-
|
|
456
|
-
# Connection parameters demonstration
|
|
457
|
-
python examples/connection_parameters_demo.py
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
### Key API Improvements
|
|
461
|
-
|
|
462
|
-
Our async-only design provides a clean, intuitive interface:
|
|
463
|
-
|
|
464
|
-
```python
|
|
465
|
-
# ✅ Clean async API (New Design)
|
|
466
|
-
async with Connection(connection_string) as conn:
|
|
467
|
-
result = await conn.execute(sql) # Intuitive!
|
|
468
|
-
rows_affected = await conn.execute_non_query(sql)
|
|
469
|
-
|
|
470
|
-
# ❌ Old confusing API (Removed)
|
|
471
|
-
# async with Connection(connection_string) as conn:
|
|
472
|
-
# result = await conn.execute_async(sql) # Confusing suffixes
|
|
473
|
-
# rows_affected = await conn.execute_non_query_async(sql)
|
|
474
|
-
```
|
|
475
|
-
|
|
476
357
|
## Development
|
|
477
358
|
|
|
478
359
|
### Building from Source
|
|
@@ -655,19 +536,6 @@ async with mssql.connect_async(conn_str) as conn:
|
|
|
655
536
|
print(f"Pool utilization: {stats['active_connections']}/{stats['connections']}")
|
|
656
537
|
```
|
|
657
538
|
|
|
658
|
-
**Features:**
|
|
659
|
-
- Async-only operations for maximum performance
|
|
660
|
-
- Automatic connection pooling with bb8
|
|
661
|
-
- Configurable pool settings via `PoolConfig`
|
|
662
|
-
- Pool statistics and monitoring
|
|
663
|
-
- Improved concurrent performance
|
|
664
|
-
- Better resource management
|
|
665
|
-
|
|
666
|
-
**Breaking Changes:**
|
|
667
|
-
- None - the API is fully backward compatible
|
|
668
|
-
- All existing code continues to work without modification
|
|
669
|
-
- Performance improvements are automatic
|
|
670
|
-
|
|
671
539
|
## Advanced Usage Patterns
|
|
672
540
|
|
|
673
541
|
### Custom Pool Configuration for Different Scenarios
|
|
@@ -756,7 +624,7 @@ async def olap_operations():
|
|
|
756
624
|
return quarterly_report
|
|
757
625
|
```
|
|
758
626
|
|
|
759
|
-
##
|
|
627
|
+
## API Reference
|
|
760
628
|
|
|
761
629
|
### Common Issues
|
|
762
630
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
fastmssql-0.2.7.dist-info/RECORD,,
|
|
2
|
+
fastmssql-0.2.7.dist-info/WHEEL,sha256=XiGjjeJC2k7oCSYs1QNLi9iFDhofhstbUV6w7vMmp_k,104
|
|
3
|
+
fastmssql-0.2.7.dist-info/METADATA,sha256=pF7dtgu6k6kSZfz-_kLln9dlcjYgWi5yKzbu-L02TU0,24664
|
|
4
|
+
fastmssql-0.2.7.dist-info/licenses/LICENSE,sha256=NwufX3BNj7RvVtnrshWhkpFOLvWc_YVpGpr3UZGFz_E,4765
|
|
5
|
+
fastmssql/__init__.py,sha256=1DZiNk-l6MFhxGVWikdxDQiaXh_6FyhQWtz6UxyxO9s,29041
|
|
6
|
+
fastmssql/fastmssql.cpython-310-darwin.so,sha256=eg7lyvmzCoBdHhCLNEDckIXxe2PLg1yBHnnaxjL1rC4,3858048
|