1- # asyncmy - A fast asyncio MySQL/MariaDB driver
1+ # asyncmy — Fast asyncio MySQL/MariaDB driver
22
3- [ ![ image ] ( https://img.shields.io/pypi/v/asyncmy.svg?style=flat )] ( https://pypi.python .org/pypi/asyncmy )
4- [ ![ image ] ( https://img.shields.io/github/license/long2ice/asyncmy )] ( https://github.com/long2ice/asyncmy )
5- [ ![ pypi ] ( https://github.com/long2ice/asyncmy/actions/workflows/pypi .yml/badge.svg )] ( https://github.com/long2ice/asyncmy/actions/workflows/pypi .yml )
6- [ ![ ci ] ( https://github.com/long2ice/asyncmy/actions/workflows/ci .yml/badge.svg )] ( https://github.com/long2ice/asyncmy/actions/workflows/ci .yml )
3+ [ ![ PyPI ] ( https://img.shields.io/pypi/v/asyncmy.svg )] ( https://pypi.org/pypi/asyncmy )
4+ [ ![ License ] ( https://img.shields.io/github/license/long2ice/asyncmy )] ( https://github.com/long2ice/asyncmy )
5+ [ ![ CI ] ( https://github.com/long2ice/asyncmy/actions/workflows/ci .yml/badge.svg )] ( https://github.com/long2ice/asyncmy/actions/workflows/ci .yml )
6+ [ ![ Release ] ( https://github.com/long2ice/asyncmy/actions/workflows/pypi .yml/badge.svg )] ( https://github.com/long2ice/asyncmy/actions/workflows/pypi .yml )
77
8- ## Introduction
9-
10- ` asyncmy ` is a fast asyncio MySQL/MariaDB driver, which reuse most of [ pymysql] ( https://github.com/PyMySQL/PyMySQL )
11- and [ aiomysql] ( https://github.com/aio-libs/aiomysql ) but rewrite core protocol with [ cython] ( https://cython.org/ ) to
12- speedup.
8+ ` asyncmy ` is a fast asyncio MySQL/MariaDB driver. It reuses most of [ PyMySQL] ( https://github.com/PyMySQL/PyMySQL ) and [ aiomysql] ( https://github.com/aio-libs/aiomysql ) while rewriting the core protocol in [ Cython] ( https://cython.org/ ) for better performance.
139
1410## Features
1511
16- - API compatible with [ aiomysql] ( https://github.com/aio-libs/aiomysql ) .
17- - Faster by [ cython ] ( https://cython.org/ ) .
18- - MySQL replication protocol support with ` asyncio ` .
19- - Tested both MySQL and MariaDB in [ CI ] ( https://github.com/long2ice/asyncmy/blob/dev/.github/workflows/ci.yml ) .
12+ - ** API compatible** with [ aiomysql] ( https://github.com/aio-libs/aiomysql )
13+ - ** Faster** via [ Cython ] ( https://cython.org/ ) -compiled core
14+ - ** MySQL replication protocol** with asyncio ( [ BinLogStream ] ( https://github.com/long2ice/asyncmy/blob/dev/asyncmy/replication/binlogstream.py ) )
15+ - ** CI-tested ** on MySQL and MariaDB ( [ workflow ] ( https://github.com/long2ice/asyncmy/blob/dev/.github/workflows/ci.yml ) )
2016
2117## Benchmark
2218
23- The result comes from [ benchmark ] ( ./benchmark ) .
19+ asyncmy demonstrates excellent performance across realistic workloads:
2420
25- > The device is iMac Pro(2017) i9 3.6GHz 48G and MySQL version is 8.0.26.
21+ | Test | asyncmy Rank | Performance |
22+ | ---- | ------------ | ----------- |
23+ | ** Connection Pool** (2k queries) | 🏆 ** #1 /2** | ~ 10,500 qps (consistently 22-28% faster than aiomysql) |
24+ | ** Large Result Set** (50k rows) | #2 /4 | ~ 0.090s (2x faster than aiomysql, close to mysqlclient) |
25+ | ** Concurrent Queries** (50 queries) | #1 -2/2 | Comparable to aiomysql |
26+ | ** Batch Insert** (10k rows) | Variable | Results vary by run |
2627
27- ![ benchmark ] ( ./images/benchmark.png )
28+ ** Recent optimizations (v0.2.12) ** delivered significant performance improvements:
2829
29- ### Conclusion
30+ - ** Buffer Management** : Zero-copy fast path for single-packet reads
31+ - ** DateTime Parsing** : Fast string slicing replacing regex
32+ - ** Row Parsing** : Pre-allocated lists and C-level indexing in hot path
33+ - ** Protocol Parsing** : Inlined length-coded string reads with fast path for common cases
3034
31- - There is no doubt that ` mysqlclient ` is the fastest MySQL driver.
32- - All kinds of drivers have a small gap except ` select ` .
33- - ` asyncio ` could enhance ` insert ` .
34- - ` asyncmy ` performs remarkable when compared to other drivers.
35+ 📊 ** [ View detailed benchmarks →] ( ./benchmark/README.md ) **
3536
3637## Install
3738
38- ``` shell
39+ ** Requirements:** Python ≥ 3.9
40+
41+ ``` bash
3942pip install asyncmy
4043```
4144
42- ### Installing on Windows
45+ ### Windows
4346
44- To install asyncmy on Windows, you need to install the tools needed to build it .
47+ asyncmy uses Cython extensions; on Windows you need ** Microsoft C++ Build Tools ** to build them .
4548
46- 1 . Download * Microsoft C++ Build Tools* from https://visualstudio.microsoft.com/visual-cpp-build-tools/
47- 2 . Run CMD as Admin (not required but recommended) and navigate to the folder when your installer is downloaded
48- 3 . Installer executable should look like this ` vs_buildtools__XXXXXXXXX.XXXXXXXXXX.exe ` , it will be easier if you rename
49- it to just ` vs_buildtools.exe `
50- 4 . Run this command (Make sure you have about 5-6GB of free storage)
49+ 1 . Download [ Microsoft C++ Build Tools] ( https://visualstudio.microsoft.com/visual-cpp-build-tools/ ) .
50+ 2 . Open CMD as Administrator (recommended) and ` cd ` to the folder ** where** the installer was downloaded.
51+ 3 . Rename the installer (e.g. ` vs_buildtools__XXXXXXXXX.XXXXXXXXXX.exe ` ) to ` vs_buildtools.exe ` for convenience.
52+ 4 . Run (ensure ~ 5–6GB free disk space):
5153
52- ``` shell
53- vs_buildtools.exe --norestart --passive --downloadThenInstall --includeRecommended --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools
54- ```
54+ ``` bash
55+ vs_buildtools.exe --norestart --passive --downloadThenInstall --includeRecommended --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools
56+ ```
5557
56- 5 . Wait until the installation is finished
57- 6 . After installation will finish, restart your computer
58- 7 . Install asyncmy via PIP
58+ 5 . Wait for installation to complete, then restart your computer.
59+ 6 . Install asyncmy:
5960
60- ``` shell
61- pip install asyncmy
62- ```
61+ ``` bash
62+ pip install asyncmy
63+ ```
6364
64- Now you can uninstall previously installed tools .
65+ You can uninstall the Build Tools afterward if desired .
6566
6667## Usage
6768
68- ### Use ` connect `
69+ ### ` connect `
6970
70- ` asyncmy ` provides a way to connect to MySQL database with simple factory function ` asyncmy.connect() ` . Use this
71- function if you want just one connection to the database, consider connection pool for multiple connections.
71+ Use ` asyncmy.connect() ` for a single connection. For many concurrent connections, use a [ connection pool] ( #pool ) .
7272
7373``` py
7474import asyncio
@@ -78,41 +78,42 @@ from asyncmy import connect
7878from asyncmy.cursors import DictCursor
7979
8080
81- async def run ():
82- conn = await connect(user = os.getenv(" DB_USER" ), password = os.getenv(" DB_PASSWORD" , " " ))
81+ async def main ():
82+ conn = await connect(
83+ user = os.getenv(" DB_USER" ),
84+ password = os.getenv(" DB_PASSWORD" , " " ),
85+ )
8386 async with conn.cursor(cursor = DictCursor) as cursor:
8487 await cursor.execute(" CREATE DATABASE IF NOT EXISTS test" )
8588 await cursor.execute("""
86- """
87- CREATE TABLE IF NOT EXISTS test.`asyncmy` (
88- `id ` int primary key AUTO_INCREMENT ,
89- `decimal` decimal(10 , 2 ),
90- `date` date,
91- `datetime` datetime,
92- `float ` float ,
93- `string` varchar(200 ),
94- `tinyint` tinyint
95- ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci
96- """ .strip()
97- )
89+ CREATE TABLE IF NOT EXISTS test.`asyncmy` (
90+ `id` int PRIMARY KEY AUTO_INCREMENT,
91+ `decimal` decimal(10, 2),
92+ `date` date,
93+ `datetime` datetime,
94+ `float` float,
95+ `string` varchar(200),
96+ `tinyint` tinyint
97+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
98+ """ .strip())
9899 await conn.ensure_closed()
99100
100101
101102if __name__ == " __main__" :
102- asyncio.run(run ())
103+ asyncio.run(main ())
103104```
104105
105- ### Use `pool`
106+ ### Pool
106107
107- `asyncmy` provides connection pool as well as plain Connection objects .
108+ For multiple connections, use a connection pool. Pass the same kwargs as ` connect() ` (e.g. ` host ` , ` user ` , ` password ` ) .
108109
109110``` py
110- import asyncmy
111111import asyncio
112+ import asyncmy
112113
113114
114- async def run ():
115- pool = await asyncmy.create_pool()
115+ async def main ():
116+ pool = await asyncmy.create_pool(host = " localhost " , user = " root " , password = " " )
116117 async with pool.acquire() as conn:
117118 async with conn.cursor() as cursor:
118119 await cursor.execute(" SELECT 1" )
@@ -121,29 +122,30 @@ async def run():
121122 pool.close()
122123 await pool.wait_closed()
123124
124- if __name__ == '__main__':
125- asyncio.run(run())
125+
126+ if __name__ == " __main__" :
127+ asyncio.run(main())
126128```
127129
128130## Replication
129131
130- `asyncmy` supports MySQL replication protocol
131- like [python-mysql-replication](https://github.com/noplay/python-mysql-replication), but powered by `asyncio`.
132+ asyncmy supports the MySQL replication protocol (like [ python-mysql-replication] ( https://github.com/noplay/python-mysql-replication ) ) over asyncio.
132133
133134``` py
135+ import asyncio
136+
134137from asyncmy import connect
135138from asyncmy.replication import BinLogStream
136- import asyncio
137139
138140
139- async def run ():
141+ async def main ():
140142 conn = await connect()
141143 ctl_conn = await connect()
142144
143145 stream = BinLogStream(
144146 conn,
145147 ctl_conn,
146- 1,
148+ server_id = 1 ,
147149 master_log_file = " binlog.000172" ,
148150 master_log_position = 2235312 ,
149151 resume_stream = True ,
@@ -155,19 +157,18 @@ async def run():
155157 await ctl_conn.ensure_closed()
156158
157159
158- if __name__ == ' __main__' :
159- asyncio.run(run ())
160+ if __name__ == " __main__" :
161+ asyncio.run(main ())
160162```
161163
162- ## ThanksTo
164+ ## Acknowledgments
163165
164- > asyncmy is build on top of these awesome projects.
166+ asyncmy builds on these projects:
165167
166- - [pymysql](https://github/pymysql/PyMySQL), a pure python MySQL client.
167- - [aiomysql](https://github.com/aio-libs/aiomysql), a library for accessing a MySQL database from the asyncio.
168- - [python-mysql-replication](https://github.com/noplay/python-mysql-replication), pure Python Implementation of MySQL
169- replication protocol build on top of PyMYSQL.
168+ - [ PyMySQL] ( https://github.com/PyMySQL/PyMySQL ) — pure Python MySQL client
169+ - [ aiomysql] ( https://github.com/aio-libs/aiomysql ) — asyncio MySQL driver
170+ - [ python-mysql-replication] ( https://github.com/noplay/python-mysql-replication ) — MySQL replication protocol (pure Python, on top of PyMySQL)
170171
171172## License
172173
173- This project is licensed under the [Apache-2.0](./LICENSE) License.
174+ [ Apache-2.0] ( ./LICENSE )
0 commit comments