使用 "Insert or Ignore" 语句加速 Python executemany
Speed up Python executemany with "Insert or Ignore"-Statement
我是 pyodbc 的新手,运行 遇到 executemany
需要相当长的时间的问题。在对脚本进行基准测试时,将 962 行插入 table 大约需要 15 分钟。如果可能的话,我想加快这个查询的速度。
我运行以下脚本:
cursor = conn.cursor()
parsed_json = get_parsed_json_Event_Log()
print(f'Gathering data from API found {len(parsed_json)} entries')
cursor.fast_executemany=True
cursor.executemany(f"""
IF NOT EXISTS (SELECT 1 FROM {schema_name}.{table_name} WHERE id = ?)
INSERT INTO {schema_name}.{table_name}
SELECT ?,
?,
DATEADD(s, ?, '19700101 02:00:00:000'),
?,
?,
DATEADD(s, ?, '19700101 02:00:00:000'),
?,
?,
?,
?,
?,
?;""", parsed_json)
我正在使用 python 3.8.6 和 Azure SQL 服务器。解析后的 JSON 采用指定的序列格式,由 pyodbc 文档建议。 DATEADD
函数中的施法日期信息以全局秒数提供。
我试图实现 INSERT
OR IGNORE INTO
语句,我知道这在 SQLite 中是可能的。不幸的是,我无法为 Azure SQL 服务器想出一个实现,因此必须默认为 IF NOT EXISTS
语句。
如果有人能帮助我加快脚本或改进语句以加快执行速度,那就太棒了。
我多次尝试加快查询速度并收集了一些见解,希望与可能遇到相同问题的每个人分享:
要点:
- 使用 Azure SQL 服务器时,始终尝试使用
INSERT INTO ... VALUES (...)
语句而不是 INSERT INTO ... SELECT ...
,因为它的执行速度提高了大约 350%(针对所描述的问题和使用的语法进行基准测试时).
- 我使用
INSERT INTO ... SELECT ...
的主要原因是因为特定的 DATEADD()
Cast,因为如果不在 Azure SQL 服务器中明确声明变量就无法做到这一点。
- 如果您将提供的时间转换为 python
datetime
,则可以跳过给定示例中的 DATEADD()
。如果您选择此选项,请确保在将数据插入 SQL Table 时不要使用文字字符串。除了@Charlieface 指出的不良做法外,PYODBC
在使用字符串文字输入时没有针对该数据类型的内置逻辑(这里的序列输入结构没有问题)
IF NOT EXISTS
声明真的很贵。如果可能,尽量省略它。如果您依赖于保留 table 历史记录,一个简单的解决方法是创建第二个新创建的 table,然后从那个 table 插入到未找到匹配项的原始位置。在这里您可以依赖于您的本地 SQL 实现而不是 PYODBC 实现。这种方式是迄今为止最快的。
不同的设计选择带来了以下性能改进:
INSERT INTO ... SELECT ...
对比 INSERT INTO ... VALUES (...)
:350%
- 利用第二个 table 和原生 SQL 支持:560%
我是 pyodbc 的新手,运行 遇到 executemany
需要相当长的时间的问题。在对脚本进行基准测试时,将 962 行插入 table 大约需要 15 分钟。如果可能的话,我想加快这个查询的速度。
我运行以下脚本:
cursor = conn.cursor()
parsed_json = get_parsed_json_Event_Log()
print(f'Gathering data from API found {len(parsed_json)} entries')
cursor.fast_executemany=True
cursor.executemany(f"""
IF NOT EXISTS (SELECT 1 FROM {schema_name}.{table_name} WHERE id = ?)
INSERT INTO {schema_name}.{table_name}
SELECT ?,
?,
DATEADD(s, ?, '19700101 02:00:00:000'),
?,
?,
DATEADD(s, ?, '19700101 02:00:00:000'),
?,
?,
?,
?,
?,
?;""", parsed_json)
我正在使用 python 3.8.6 和 Azure SQL 服务器。解析后的 JSON 采用指定的序列格式,由 pyodbc 文档建议。 DATEADD
函数中的施法日期信息以全局秒数提供。
我试图实现 INSERT
OR IGNORE INTO
语句,我知道这在 SQLite 中是可能的。不幸的是,我无法为 Azure SQL 服务器想出一个实现,因此必须默认为 IF NOT EXISTS
语句。
如果有人能帮助我加快脚本或改进语句以加快执行速度,那就太棒了。
我多次尝试加快查询速度并收集了一些见解,希望与可能遇到相同问题的每个人分享:
要点:
- 使用 Azure SQL 服务器时,始终尝试使用
INSERT INTO ... VALUES (...)
语句而不是INSERT INTO ... SELECT ...
,因为它的执行速度提高了大约 350%(针对所描述的问题和使用的语法进行基准测试时).- 我使用
INSERT INTO ... SELECT ...
的主要原因是因为特定的DATEADD()
Cast,因为如果不在 Azure SQL 服务器中明确声明变量就无法做到这一点。
- 我使用
- 如果您将提供的时间转换为 python
datetime
,则可以跳过给定示例中的DATEADD()
。如果您选择此选项,请确保在将数据插入 SQL Table 时不要使用文字字符串。除了@Charlieface 指出的不良做法外,PYODBC
在使用字符串文字输入时没有针对该数据类型的内置逻辑(这里的序列输入结构没有问题) IF NOT EXISTS
声明真的很贵。如果可能,尽量省略它。如果您依赖于保留 table 历史记录,一个简单的解决方法是创建第二个新创建的 table,然后从那个 table 插入到未找到匹配项的原始位置。在这里您可以依赖于您的本地 SQL 实现而不是 PYODBC 实现。这种方式是迄今为止最快的。
不同的设计选择带来了以下性能改进:
INSERT INTO ... SELECT ...
对比INSERT INTO ... VALUES (...)
:350%- 利用第二个 table 和原生 SQL 支持:560%