What does HackerNews think of asyncpg?

A fast PostgreSQL Database Client Library for Python/asyncio.

Language: Python

#10 in PostgreSQL
#31 in Python
#2 in Python
This pure Python library claims quite fabulous performance: https://github.com/MagicStack/asyncpg

I believe it because that team have done lots of great stuff but I haven't used it, I just remembered thinking it was interesting the performance was so good. Not sure how related it is to running on the asyncio loop (or which loop they used for benchmarks).

Related to ORMs/queries/performance, I have found the following combination really good:

* aiosql[0] to write raw SQL queries and having them available as python functions (discussed in [1])

* asyncpg[2] if you are using Postgres

* Map asyncpg/aiosql results to Pydantic[3] models

* FastAPI[4]

Pydantic models become the "source of truth" inside the app, they are designed as a copy of the DB schema, then functions receive and return Pydantic models in most cases.

This stack also makes me think better about my queries and the DB design. I try to make sure each endpoint makes only a couple of queries. Each query may have multiple CTEs, but it's still only a single round-trip. That also makes you think about what to prefetch or not, maybe I want to also get the data to return if the request is OK and avoid another query.

[0] https://github.com/nackjicholson/aiosql [1] https://news.ycombinator.com/item?id=24130712 [2] https://github.com/MagicStack/asyncpg [3] https://pydantic-docs.helpmanual.io/ [4] https://fastapi.tiangolo.com/

Agreed. I will never recommend an ORM, things simply spiraled out of control for medium to large-ish projects that had more than 2 developers. Even with "best practices", code ended up having a mix of raw SQL and ORM-style queries, and it was hard to reason about the code.

Since switching to asyncpg [0] these problems have vanished. It commands a deeper knowledge of actual SQL, but I would argue this knowledge is absolutely necessary and one of the disadvantages of an ORM is that it makes the SQL that is eventually run opaque.

Not sure if there are equivalents to asyncpg for other RDBMS's.

[0]: https://github.com/MagicStack/asyncpg

FastAPI is database agnostic, although tutorials talk about using SQLAlchemy (probably because it's most popular).

I am using asyncpg[1] (much more performant and provides close mapping to PostgreSQL, making it much easier to use its advanced features) through raw SQL statements without problems.

[1] https://github.com/MagicStack/asyncpg

the psycopg2 driver for PostgreSQL supports an async mode which uses PostgreSQL's full blown non-blocking API, this is what I used when I did my tests and might be what was used here. There is also the asyncpg driver that is native to PG's non-blocking API. PG is the one database that does lend itself to async because it has a fully non-blocking client library available.

https://www.postgresql.org/docs/12/libpq-async.html

https://www.psycopg.org/docs/advanced.html#green-support

https://github.com/MagicStack/asyncpg

On top of that, the author uses aiopg rather than asyncpg[1] for the async database operations, even though asyncpg is (allegedly) a whole lot faster.

1. https://github.com/MagicStack/asyncpg

Well, if performance is the objective, then I can't suggest Python, because that isn't the goal. You can still have a performant application implemented in Python, I for example had it encode video stream on the fly, but this of course is done through extensibility via C extensions and the core work wasn't really done in Python itself.

Sometimes with the right approach (mapping PostgreSQL calls 1:1) and right tooling (uvloop, Cython) you can write code in Python and still squeeze better performance than in Go[1], but you need to know what you're doing.

If you want to explore types, these resources[2][3] were useful for me.

[1] https://github.com/MagicStack/asyncpg

[2] https://mypy.readthedocs.io/en/stable/

[3] https://docs.python.org/3/library/typing.htm

I used aiohttp and it is quite good and solid (I also like that it comes with type annotations, which enables autocomplete in PyCharm), I did not have chance to compare it to FastAPI.

Regarding database access, my recommendation might not be popular, but I really like asyncpg[1]. They basically dropped DBAPI and instead created their own API that functionally matches PostgreSQL, giving you full control and increasing performance.

As a result of that you probably won't be able to use ORMs (there's SQLAlchemy driver, but as I understand it is hacky and you are losing the performance benefits).

Personally I compared my code with and without ORM and there's no change in number of lines. If you use PyCharm and configure it to connect to your database (I think that might be a pro feature) it will then automatically detect SQL in your strings provide autocomplete (including table and column names) and provide highlighting, removing all the advantages that ORM provided.

[1] https://github.com/MagicStack/asyncpg

Correct - the Django ORM is not (yet) async.

The asyncpg library[1][2] could be used for direct, asynchronous database access, from within a Django 3.x app.

The asyncpg library is a low-level async Postgres adaptor, similar to psycopg2, except that it provides much better abstractions and automatic encoding / decoding (vs just piping bytes back and forth like psycopg2), not to mention it is much faster than anything else out there. IOW, asyncpg would serve as a much better foundation for a future ORM. My best guess is that, in the future, Django's ORM will be refactored to optionally support async and will supply an adaptor for asyncpg.

1. https://github.com/MagicStack/asyncpg

2. https://magicstack.github.io/asyncpg/current/

Yes it does, and almost everything else will have performance issues except assembly. With web services, chances are that you'll hit other bottlenecks before you hit it. In python you have multiple ways to optimize performance, for example use PyPy, or various libraries like Cython that compile your performance sensitive code.

That's how asyncpg can outperform[1] some libraries that you normally would think was not possible.

[1] https://github.com/MagicStack/asyncpg

Perhaps slightly unrelated: I'm considering moving to asyncpg and using quart, which is a port of flask to async python. What I wonder if it's time to start using async python, and if these libraries are mature enough. If so, I hope libraries like this and little_pger will switch to it or support it!

https://github.com/MagicStack/asyncpg https://gitlab.com/pgjones/quart

Python's async support also seems to be getting better. There's a flask clone called Quart (http://pgjones.gitlab.io/quart/) and an async postgres client (https://github.com/MagicStack/asyncpg). It works very similar to JavaScript, with async and await keywords. I think it should provide speed and comfort especially if you're a regular JavaScript user.
One thing I've never been able to reconcile is Mike Bayer's article there, set against Yury Selivanov's reported results for `asyncpg`, which at least as they're presented do indicate a significant difference in throughput.

https://github.com/MagicStack/asyncpg

They're both incredibly experienced developers, and I don't have any good steer on the discrepancy.

Would love to see some independent benchmarking on a typical use case to get a clearer picture on how valuable (or not) asyncio is for high-throughput database operations.