【问题标题】:How to have something like fast_executemany with SQLAlchemy 1.3.18 with Sybase to improve the speed of insert into?如何在 SQLAlchemy 1.3.18 中使用 fast_executemany 和 Sybase 来提高插入速度?
【发布时间】:2020-11-27 18:55:33
【问题描述】:

我用 Python 编写了一个插入 Sybase 数据库的程序,我使用 pandas 1.0.4 和 SQLAlchemy 1.3.18。

我已经在 sybase 和我的脚本之间建立了链接,但实际上插入表格的速度真的很慢(30k 行需要 10 分钟...)

在 SQL Server 中,使用相同的代码(create_engine 中的参数 fast_executemany=True 和 dataframe.to_sql() 的参数 method='multi', chunksize = 500 除外),我已将插入时间缩短为 3 秒。

你有什么办法解决这个问题吗?

祝你有美好的一天!

【问题讨论】:

  • 使用method='multi' 违背了使用fast_executemany=True 的目的。前者使 Pandas 发出单独的 INSERT ... VALUES (...), (...), ... 语句(这就是为什么您需要合适的块大小),而后者加速 executemany()(这是 Pandas/SQLA 默认的)。
  • 好的,谢谢。但实际上它并不能解决我的问题。我不明白为什么 method='multi' 和 chunksize 在 SQL Server 上工作而在 Sybase 上不工作
  • Sybase 是否支持 INSERT 中的VALUES (...), (...), ... 子句(特别是多个元组)?不幸的是,我对 Sybase 的经验为 0,但这似乎暗示它(某些版本的“它”)没有:stackoverflow.com/questions/24635327/…
  • 我刚刚看到您发送的链接。因此,最好制作 df.read_sql_query 并使用之前创建的 Union ALL 发出一个大请求并使用循环。但这真的很无聊:(

标签: python database sqlalchemy sybase


【解决方案1】:

看起来像Sybase ASE does not support a multiple values VALUES clause in INSERT。如果您需要在单个语句中插入多个值而不是 using executemany 以简单地发出许多 INSERT 语句,则可以形成 UNION of SELECT 语句:

from sqlalchemy import union_all, select, literal

def sybase_insert(sqltable, conn, keys, data_iter):
    sel = union_all(*[select([literal(v) for v in row]) for row in data_iter])
    ins = sqltable.table.insert().from_select(keys, sel)
    conn.execute(ins)

在调用to_sql()时将函数作为method传递:

In [11]: pd.DataFrame({"A": range(3)}).to_sql("foo", con=engine, method=sybase_insert)
2020-08-10 08:29:44,474 INFO sqlalchemy.engine.base.Engine PRAGMA main.table_info("foo")
2020-08-10 08:29:44,474 INFO sqlalchemy.engine.base.Engine ()
2020-08-10 08:29:44,475 INFO sqlalchemy.engine.base.Engine PRAGMA temp.table_info("foo")
2020-08-10 08:29:44,475 INFO sqlalchemy.engine.base.Engine ()
2020-08-10 08:29:44,477 INFO sqlalchemy.engine.base.Engine 
CREATE TABLE foo (
        "index" BIGINT, 
        "A" BIGINT
)


2020-08-10 08:29:44,477 INFO sqlalchemy.engine.base.Engine ()
2020-08-10 08:29:44,477 INFO sqlalchemy.engine.base.Engine COMMIT
2020-08-10 08:29:44,478 INFO sqlalchemy.engine.base.Engine CREATE INDEX ix_foo_index ON foo ("index")
2020-08-10 08:29:44,478 INFO sqlalchemy.engine.base.Engine ()
2020-08-10 08:29:44,478 INFO sqlalchemy.engine.base.Engine COMMIT
2020-08-10 08:29:44,479 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2020-08-10 08:29:44,481 INFO sqlalchemy.engine.base.Engine INSERT INTO foo ("index", "A") SELECT ? AS anon_1, ? AS anon_2 UNION ALL SELECT ? AS anon_3, ? AS anon_4 UNION ALL SELECT ? AS anon_5, ? AS anon_6
2020-08-10 08:29:44,481 INFO sqlalchemy.engine.base.Engine (0, 0, 1, 1, 2, 2)
2020-08-10 08:29:44,481 INFO sqlalchemy.engine.base.Engine COMMIT

【讨论】:

  • 感谢您的回答。您能否告诉我您在这部分代码中使用的库:def sybase_insert(sqltable, conn, keys, data_iter): sel = union_all(*[select([literal(v) for v in row]) for row in data_iter]) ins = sqltable.table.insert().from_select(keys, sel) conn.execute(ins) 哪个库适用于 sqltable?谢谢你,祝你有美好的一天
  • 抱歉,忘记了从那个导入,添加了。
【解决方案2】:

如果您使用 SAP ASE ODBC 驱动程序,external SAP ASE (Sybase) dialect 确实支持 fast_executemany。

【讨论】:

  • 出于好奇,它与香草 odbc executemany 相比有多大不同?我记得它对带有 odbc 驱动程序的 SQL Server 产生了相当大的影响。
  • SAP ASE (Sybase) 的性能改进与 SQL Server 相当。 :)
猜你喜欢
  • 2020-11-25
  • 2021-11-15
  • 2020-09-10
  • 2016-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多