【问题标题】:How to write a pandas DataFrame directly into a Netezza Database?如何将 pandas DataFrame 直接写入 Netezza 数据库?
【发布时间】:2019-09-17 13:37:28
【问题描述】:

我在 python 中有一个 pandas DataFrame,并希望将此 DataFrame 直接写入 Netezza 数据库。

我想使用here 中描述的pandas.to_sql() 方法,但似乎此方法需要使用SQLAlchemy 连接到数据库。 问题:SQLAlchemy 不支持 Netezza。 我目前用来连接数据库的是pyodbc。但另一方面,pandas.to_sql() 不理解这一点,还是我错了?

我的解决方法是通过 pandas.to_csv() 将 DataFrame 写入 csv 文件,然后通过 pyodbc 将其发送到 Netezza 数据库。

因为我有大数据,所以先写 csv 是一个性能问题。我实际上不在乎是否必须使用 SQLAlchemy 或 pyodbc 或其他东西,但我无法改变我拥有 Netezza 数据库的事实。

我知道道义论项目,但正如作者所说,它“远未完成,有很多错误”。 我得到了这个包的工作(见下面我的解决方案)。但如果有人现在有更好的解决方案,请告诉我!

我想通了。对于我的解决方案,请参阅接受的答案。

【问题讨论】:

  • 您是否尝试使用方言来查看它是否适用于您的特定情况?当我接手 sqlalchemy-access 方言时,我做的第一件事就是让 pandas to_sql 工作。
  • 查看pyodbc.drivers() 返回的列表,了解您的 Python 应用程序可以使用哪些驱动程序。您在该列表中看到 Netezza 驱动程序了吗?
  • 是的。 “NetezzaSQL”在列表中。我摆脱了pyodbc.InterfaceError。该错误提示我在 Windows ODBC 数据源管理员工具中添加数据源并使用它,而不是尝试“手动”输入服务器地址。然后它得到驱动程序。我不知道这是否是正常行为,因为在 pyodbc 中没有必要这样做。所以我使用engine = create_engine(netezza://ODBCDataSourceName) 而不是engine = create_engine(netezza://usr:pass@address:port/database_name) 它仍然不起作用。我会尽快更新我的问题。
  • 感谢您的努力,戈德!我找到了解决方案。编辑了我的问题以包含它。
  • 感谢您抽出宝贵时间跟进。这里的人们发布他们的解决方案作为他们自己问题的答案是很常见的。这使其他人更容易受益,如果您接受自己的答案,则可以将问题标记为“已解决”。

标签: python pandas sqlalchemy pyodbc netezza


【解决方案1】:

解决方案

我找到了一个解决方案,我想与遇到相同问题的每个人分享。 我尝试了deontologician 的 netezza 方言,但它不适用于 python3,所以我做了一个 fork 并纠正了一些编码问题。我上传到 github,它可以在 here 获得。请注意,我只是做了一些小改动,这主要是道义学家的工作,没有人维护它。

拥有 netezza 方言,我得到了 pandas.to_sql() 直接使用 Netezza 数据库:

import netezza_dialect
from sqlalchemy import create_engine

engine = create_engine("netezza://ODBCDataSourceName")

df.to_sql("YourDatabase", 
          engine,  
          if_exists='append',
          index=False,
          dtype=your_dtypes,
          chunksize=1600,
          method='multi')

to_sql()参数的一点解释:

如果您不想永远将 pandas 写入数据库,则使用 method='multi' 参数是必要的。因为没有它,它将每行发送一个 INSERT 查询。您可以使用'multi',也可以定义自己的插入方法。请注意,您必须至少拥有pandas v0.24.0 才能使用它。 See the docs 了解更多信息。

使用method='multi' 时,您可能会超出参数限制(至少对我来说是这样)。就我而言,它是 1600,所以我必须添加 chunksize=1600 以避免这种情况。

注意

如果您收到如下警告或错误:

C:\Users\USER\anaconda3\envs\myenv\lib\site-packages\sqlalchemy\connectors\pyodbc.py:79: SAWarning: No driver name specified; this is expected by PyODBC when using DSN-less connections
  "No driver name specified; "
pyodbc.InterfaceError: ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified (0) (SQLDriverConnect)')

然后您可能会通过以下方式连接到数据库

engine = create_engine(netezza://usr:pass@address:port/database_name)

您必须在 Windows 的 ODBC 数据源管理器工具中设置数据库,然后使用您在此处定义的名称。

engine = create_engine(netezza://ODBCDataSourceName)

那么找到驱动应该没有问题了。

【讨论】:

    【解决方案2】:

    我知道你自己已经回答了这个问题(感谢分享解决方案)

    关于向 Netezza 写入大数据的一般性评论: 我总是选择将数据写入文件,然后使用外部表/ODBC 接口插入数据。您可以在同一时间范围内插入数百万行,而不是一次插入 1600 行。

    我们在平面文件和 CSV 中使用 UTF8 数据,除非您要加载可能需要固定宽度文件的二进制数据。

    我不是蟒蛇,但我希望你能关注我...

    如果您需要文档链接,可以从这里开始:https://www.ibm.com/support/knowledgecenter/en/SSULQD_7.2.1/com.ibm.nz.load.doc/c_load_create_external_tbl_syntax.html

    【讨论】:

    • 感谢您的信息。你说的对。 1600 参数限制对我来说是一个惊喜,对我来说是一个缺点。我对数据库比较陌生,也许我的想法很天真。但是假设我的代码和系统内存中有数百万行的数据。我幼稚的想法是,我想直接将其写入 netezza,而不是先写入 csv 文件,该文件需要转换为 ASCII 和时间将文件写入 HDD 以再次打开它并将其上传到 netezza。你是对的:由于数据量很大,我更喜欢保存二进制而不是 CSV。
    • 不幸的是,您需要将其转换为数据库支持的格式,没有“二进制”插入选项。我指的是包含 PDF 文件等的数据列。
    • UTF8-CSV 可能是最好的。研究 netezza 外部表的“转义”功能,以便处理您需要的四个“特殊字符:行分隔符、列分隔符、转义字符、字符串引号。我通常(以相同的顺序)Chr(13),Chr(11),chr(92),chr(34) - 或者他们在“公民生活”中经过:回车,制表符,反斜杠,双引号
    • 我理解您的犹豫,文件 I/O 比 CPU/RAM 速度慢得多...但是您有一个 TCP/IP 网络和一个带有 sloooow 代码的 ODBC 驱动程序。在这些条件下,不要期望超过 40MB/秒。此外,netezza 上的外部表处理也相当不错。如果您在客户端(熊猫)端使用 Linux/Unix,请查看文件管道。这样,所有 I/O 都保存在内存中,并且您仍然可以绕过 odbc 类型转换代码,这是您尝试避免文件时真正的瓶颈。换句话说:相信我:文件更快 - 直观与否 :)
    • 就像@LarsGOlsen 描述的那样,将数据写入文件,然后使用transient external table 加载数据。这意味着您将在某个位置的外部文件顶部创建一个 INSERT 语句以加载数据。文档应该有更多关于如何的信息
    猜你喜欢
    • 2019-06-23
    • 2013-07-22
    • 2020-02-21
    • 2020-06-12
    • 1970-01-01
    • 2018-12-01
    • 2023-03-13
    • 1970-01-01
    • 2020-01-11
    相关资源
    最近更新 更多