Una encuesta rápida de colegas en mi proyecto actual mostró que con las palabras "ORM y trabajando con la base de datos" en la gran mayoría de los casos suenan las palabras "Alchemy" y "Django ORM". El conocimiento de estas dos palabras, en general, es suficiente para escribir código limpio, ordenado y funcional. Pero expandir los horizontes de ingeniería no ha perjudicado a nadie hasta ahora, por lo que hoy agregaremos a nuestra imagen del mundo algunas piezas interesantes (tal vez hasta este día desconocidas) para trabajar con la base de datos.

Yoyo
Hoy, cualquier ORM viene con un sistema interno de migración de base de datos. Un enfoque simple y genial, cuando ORM monitorea la estructura de las tablas, en general, se adapta a todos. Pero esta solución tiene un caso en el que es inconveniente usarla:
Hay chicos que figuaten solicitudes en una base de datos, sin pasar por ORM. Esto usa algo como asyncpg y una pequeña mancha auto escrita para simplificar la compilación de solicitudes.
¿Por qué estos chicos están renunciando a las comodidades de ORM? Sí, porque cualquier contenedor para la base de datos consume una cierta cantidad de recursos del sistema, y estos tipos necesitan escribir código de alto rendimiento. Lanzaron ORM, y de alguna manera necesitan migrar la base.
- Los migrantes incorporados pueden tener sus propios puntos de vista específicos sobre la vinculación e indexación de registros. A veces no es posible vencer estas vistas de ORM en la estructura de la tabla; tiene que corregir las correcciones de la consulta usted mismo.
En ambos casos, es conveniente usar migraciones manuales: no confiamos en los modelos ORM, pero con nuestras manos escribimos las instrucciones SQL necesarias y las introducimos en un migrador simple que aplica secuencialmente cambios estructurales a la base de datos.
El resultado es una estructura de tabla limpia, comprensible y totalmente manejable, compilada sabiamente.
Para este enfoque manual, hay un migrador de esquema de base de datos yoyo .
pip install yoyo-migrations
A continuación, todo el trabajo de gestión de la migración se realiza utilizando el ejecutable yoyo
yoyo new ./migrations -m "Add column to foo"
El comando crea un archivo en el que puede ingresar una o más instrucciones para migrar el esquema
from yoyo import step steps = [ step("CREATE TABLE foo (id INT, bar VARCHAR(20), PRIMARY KEY (id))", "DROP TABLE foo"), ]
Después de esta migración, puede pasar a la base
yoyo apply --database postgresql://scott:tiger@localhost/db ./migrations
Todo es simple, como los registros. Y al mismo tiempo, tiene un control absolutamente completo sobre el aspecto de la base de datos.
Hay dos desventajas en este enfoque.
- El conjunto de campos en las tablas y sus parámetros deberán ir seguidos de identificadores. Cada cambio lleva a la necesidad de escribir ALTER TABLE usted mismo, se pierde la capacidad de migrar todo con un solo clic.
- La fusión de tales migraciones también tendrá que ser siempre con las manos y la cabeza. Esto, por supuesto, es un trabajo superfluo. Pero en la práctica, los conflictos y las complejas fusiones de la migración son raros.
Pipí

Un ORM pequeño y no el más popular (aunque se ha escrito aquí más de una vez), que, sin embargo, tiene su propia audiencia.
Peewee está diseñado para ser el contenedor más estúpido y simple para la base de datos, con el mecanismo de ejecución de consultas más comprensible y un código fácil de leer.
Users.select().where( Users.user_id == user_id ).get()
A pesar de su simplicidad, minimalismo y una pequeña cantidad de código, peewee tiene todo lo que se necesita para un trabajo sensato.
- Rendimiento adecuado (aunque no es la velocidad de ejecución de consultas más rápida)
- Todas las ventajas necesarias: varios conjuntos de campos, relaciones entre entidades, grupos de conexiones, conjuntos de complementos y extensiones.
- Incluso hay un asincronismo más o menos sensato agregado por el módulo peewee_async de terceros.
Pony orm
Pony es un envoltorio legendario. La capa de base de datos escrita usando este ORM puede acelerar la parte posterior de otras soluciones a veces. No hay magia en su velocidad, hay una política muy competente de almacenamiento en caché de solicitudes a las bases de datos, montones de optimizaciones y trucos con el código. En total, esto lleva al hecho de que el Pony fríe a velocidad de caballo.
El menos se puede llamar la sintaxis de consulta en este ORM: es muy específico, ya que utiliza generadores, lambdas y otros bollos de lenguaje Python.
query = select(c for c in Customer if sum(o.total_price for o in c.orders) > 1000) Product.select().order_by(lambda p: desc(sum(p.order_items.quantity))).first()
Este enfoque requiere un cierto colapso del cerebro.
Oruga de tortuga

Al profundizar en varios repositorios que admiten mascotas, encontré una colección de pruebas de diferentes ORM con mediciones de velocidad. Además del Pony ORM ya mencionado, un cierto ORM de Tortuga apareció en la lista de los más rápidos. Está claro que los resultados de la prueba dependen de quién escribe las pruebas y cómo se ejecutan, pero es necesario mirar más de cerca esto.
Tortoise es un proyecto relativamente joven, que todavía está en desarrollo activo. El buen rendimiento de esta biblioteca se explica por el hecho de que ORM no contiene nada superfluo y está listo para funcionar de forma asincrónica. Y también supone el uso de uvloop , que funciona más rápido que los ciclos de eventos nativos del pitón.
Este ORM todavía es demasiado crudo para usarlo en combate (por ejemplo, hasta que se implementen los grupos de conexiones), pero debe observar el desarrollo de esta lib. Si todo va bien con los desarrolladores, en el próximo año obtendremos un contenedor realmente rápido para la base de datos con buena velocidad y sin una sintaxis extraña al estilo de Pony.