Ann*_*wan 19 python sqlalchemy
考虑以下三种使用sqlalchemy ORM插入对象的方法:
(1)
for obj in objects:
session.add(obj)
Run Code Online (Sandbox Code Playgroud)
(2)
session.add_all(objects)
Run Code Online (Sandbox Code Playgroud)
(3)
session.bulk_save_objects(objects)
Run Code Online (Sandbox Code Playgroud)
假设长度objects[]为50000
50000插入 SQL 查询?1SQL 查询?1SQL 查询?我知道这三种方法在速度上差别很大。但是底层实现细节有什么区别?
Ilj*_*ilä 19
(2) 基本上实现为 (1),如果 ORM 必须获取生成的值,例如主键,则两者都可能在刷新期间发出 50,000 次插入。如果这 50,000 个对象具有级联关系,它们甚至可能发出更多信息。
In [4]: session.add_all([Foo() for _ in range(5)])
In [5]: session.commit()
BEGIN (implicit)
INSERT INTO foo DEFAULT VALUES RETURNING foo.id
{}
... (repeats 3 times)
INSERT INTO foo DEFAULT VALUES RETURNING foo.id
{}
COMMIT
Run Code Online (Sandbox Code Playgroud)
如果您事先提供主键和其他数据库生成的值,则Session可以在参数匹配时将单独的插入组合到单个“executemany”操作中。
In [8]: session.add_all([Foo(id=i) for i in range(5)])
In [9]: session.commit()
BEGIN (implicit)
INSERT INTO foo (id) VALUES (%(id)s)
({'id': 0}, {'id': 1}, {'id': 2}, {'id': 3}, {'id': 4})
COMMIT
Run Code Online (Sandbox Code Playgroud)
如果您的 DB-API 驱动程序使用允许它发出包含多个数据的单个语句的方法实现executemany()或等效,那么它可能会导致单个查询。例如在executemany_mode='values'为上述启用Postgresql 日志包含后
LOG: statement: INSERT INTO foo (id) VALUES (0),(1),(2),(3),(4)
Run Code Online (Sandbox Code Playgroud)
批量操作会跳过大部分Session机制——例如持久化相关对象——以换取性能提升。例如,默认情况下它不获取默认值,例如主键,这允许它尝试批量更改操作和参数匹配的较少“executemany”操作。
In [12]: session.bulk_save_objects([Foo() for _ in range(5)])
BEGIN (implicit)
INSERT INTO foo DEFAULT VALUES
({}, {}, {}, {}, {})
In [13]: session.commit()
COMMIT
Run Code Online (Sandbox Code Playgroud)
它可能仍会发出多个语句,同样取决于数据和正在使用的 DB-API 驱动程序。该文档是一个很好的阅读。
随着psycopg2快速执行助理启用PostgreSQL的日志上面产生
LOG: statement: INSERT INTO foo DEFAULT VALUES;INSERT INTO foo DEFAULT VALUES;INSERT INTO foo DEFAULT VALUES;INSERT INTO foo DEFAULT VALUES;INSERT INTO foo DEFAULT VALUES
Run Code Online (Sandbox Code Playgroud)
换句话说,多个语句已加入到发送到服务器的“单个”语句中。
因此,最终所有 3 个问题的答案都是“视情况而定”,这当然看起来令人沮丧。
| 归档时间: |
|
| 查看次数: |
9888 次 |
| 最近记录: |