sqlalchemybulk_insert_mappings生成大量插入批次,这是可以避免的吗?

Ste*_*eve 3 python database optimization performance sqlalchemy

我有大量对象需要通过 sqlalchemy 插入到 Oracle 数据库中。

使用单独的插入需要花费相当长的时间才能执行。经过搜索后,很明显有更有效的批量插入方法,bulk_insert_mappings、bulk_save_objects 等。这些方法比单独插入的性能更好。然而,我注意到他们似乎将插入分成大约 8 个左右的分组。是否可以将此批量大小增加到 1000 左右?

我一直在使用的性能文档是: http: //docs.sqlalchemy.org/en/latest/faq/performance.html

render_nulls 标志似乎没有效果。如果有帮助的话,我正在使用 cx_Oracle 驱动程序。

额外参考:

session.bulk_insert_mappings(MY_OBJECT, my_object_dicts_for_insert)

根据“after_cursor_execute”事件的测量,生成大约 len(my_object_dicts_for_insert)/8 条语句。有没有办法从 sqlalchemy 或数据库来调整这种行为?

谢谢!

Ste*_*eve 7

发现问题了,这是我对 render_nulls 标志的理解。

根据描述,我认为如果提供了具有不同键的字典列表,那么它们将用空值填充以允许单个插入语句。

这不是它的工作原理,您必须确保您的字典列表具有相同的键,并且用 None 填充未使用的字段。然后,当 render_nulls 设置为 True 时,空值将被插入到具有 None 值的列中,从而允许单个插入语句。

例子:

# This results in 2 inserts
my_objects = [{'a': 1, 'b': 2}, {'a': 1}]
session.bulk_insert_mappings(MY_OBJECT, my_objects, render_nulls=True)

# This results in 2 inserts
my_objects = [{'a': 1, 'b': 2}, {'a': 1}]
session.bulk_insert_mappings(MY_OBJECT, my_objects, render_nulls=False)

# This results in 2 inserts
my_objects = [{'a': 1, 'b': 2}, {'a': 1, 'b': None}]
session.bulk_insert_mappings(MY_OBJECT, my_objects, render_nulls=False)

# This results in 1 insert - BETTER PERFORMANCE
my_objects = [{'a': 1, 'b': 2}, {'a': 1, 'b': None}]
session.bulk_insert_mappings(MY_OBJECT, my_objects, render_nulls=True)
Run Code Online (Sandbox Code Playgroud)

这会带来相当大的性能提升,对我来说,性能提高了大约 10 倍。

请注意,使用 render_nulls 时可能会产生副作用,请阅读此处的文档:http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.bulk_insert_mappings

如果您无法使用 render_nulls 标志,无法用 None 填充您的字典,或者不希望增加发送空值的带宽,您可以通过按字典的键集对对象列表进行分组来提高执行插入的数量。

例子:

# This will result in 2 inserts - BETTER PERFORMANCE
my_objects = [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}, {'a': 4}]
session.bulk_insert_mappings(MY_OBJECT, my_objects)
# This will result in 3 inserts
my_objects = [{'a': 1, 'b': 2}, {'a': 4}, {'a': 2, 'b': 3}]
session.bulk_insert_mappings(MY_OBJECT, my_objects)
Run Code Online (Sandbox Code Playgroud)