【问题标题】:loading huge XLS data into Oracle using python使用 python 将大量 XLS 数据加载到 Oracle
【发布时间】:2015-07-31 04:58:15
【问题描述】:

我有一个超过 3 万条记录的 XLS 文件,我需要使用 python 2.7 将其转储到 Oracle 12C DB(直接转储)中。

我正在使用 Cx_Oracle python 包来建立与 Oracle 的连接,但是读取和转储 XLS(使用 openpyxl pckg)非常慢,并且性能会降低数千/百万条记录。

从脚本的角度来看,使用了两种方式-

  1. 我尝试过批量加载,方法是读取数组中的所有值,然后使用游标准备(使用绑定变量)和游标 fetchmany 转储它。这不适用于大量数据。

  2. 在获取数据时迭代加载数据。即使这种方式也存在性能问题。

作为最佳实践,我可以部署哪些选项和技术/包以将大量数据从 XLS 加载到 Oracle DB?是否建议通过脚本加载大量数据,或者我是否必须使用 ETL 工具? 到目前为止,我只能通过 python 脚本选择,所以请回答前者

【问题讨论】:

    标签: python oracle cx-oracle


    【解决方案1】:

    如果可以将您的 excel 文件导出为 CSV,那么您只需使用 sqlldr 将文件加载到数据库中

    【讨论】:

    • 这是最好的选择。您能否将您的 xls 转换为 csv 或者是否存在需要您进行预处理的结构问题?有时 Python 可能会感觉很快,但是当你有一个巨大的表时,它会减慢你的速度。你应该通过 oracles sqlldr 进行引导,它针对加载进行了优化,并且速度会更快。
    • 我可以将 XLS 转换为 CSV。我可以在查看批处理文件自动化解决方案时从 Python 调用 SQL 加载程序吗?
    • 你不需要python,sqlldr是一个oracle工具,用于加载db中的数据,速度极快。关于 sqlldr 的一些信息:orafaq.com/wiki/SQL*Loader_FAQ。最好与您的 dba 讨论如何使用 sqlldr
    • 是的,但是每次都必须通过 sqlldr 手动上传 CSV。我正在寻找更多的自动化解决方案,其中 cron 作业在给定时间运行脚本
    • Python 加载大数据文件的性能很差。使用 sqlldr 并对其进行了批处理脚本。Python 脚本在进行其他转换之前在内部调用该脚本,所以它成功了。谢谢!
    【解决方案2】:

    基本上对于大容量数据,任何语言都会在 I/O 上受到压力,C 除外。最好的方法是使用数据库供应商提供的本机工具/实用程序。 对于 oracle,正确的选择是 SQL Loader。

    请参阅此链接以获取快速教程 http://www.thegeekstuff.com/2012/06/oracle-sqlldr/

    给你……运行 SQL Loader 并返回返回码、输出和错误的示例代码

    sql_ld_command = ['sqlldr ',  'uid/passwd', 'CONTROL=', 
    'your_ctrl_file_path', 'DATA=', 'your_data_file_path']   
    
    sql_ldr_proc  = subprocess.Popen(sql_ld_command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE)   
    
    out, err  = sql_ldr_proc.communicate()  
    retn_code = sql_ldr_proc.wait()
    

    【讨论】:

      【解决方案3】:

      所有步骤如下:加载 xlsx,生成 csv(制表符分隔)和 ctrl 文件,使用 sqlldr 加载。

      # %%
      import sys
      import pandas as pd
      import subprocess
      # %%
      user = 'in_user_name'
      password = 'in_password'
      host = 'in_host'
      database = 'in_service_name'
      in_file = r"in_file.xlsx"
      in_sheet_name = 'in_sheet'
      tablename = 'in_table'
      
      # %%
      df = pd.read_excel(in_file, sheet_name=in_sheet_name)
      print(f"Loaded {df.shape[0]} records from {in_file}")
      # %%
      inflie = f'{tablename}.csv'
      controlfile = f'{tablename}.ctrl'
      # %%,
      df.to_csv(inflie, index=False, sep='\t',)
      # %%
      columns = df.columns.tolist()
      with open(controlfile, 'w') as file:
          header = f"""OPTIONS (SKIP=1, DIRECT=TRUE ) 
      LOAD DATA
      INFILE '{inflie}' 
      BADFILE '{tablename}.bad'
      DISCARDFILE '{tablename}.dsc'
      TRUNCATE
      INTO TABLE {tablename}
      FIELDS TERMINATED BY X'9'  
      TRAILING NULLCOLS
      ( """
          file.write(header)
          for c in columns[:-1]:
              file.write(f'{c},\n')
          file.write(f'{columns[-1]})')
      # %%
      sqlldr_command = f"""sqlldr USERID='{user}/{password}@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={host})(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME ={database}) ))'  control={controlfile}"""
      print(f"Running sqlldr. Log file: {tablename}.log")
      subprocess.call(sqlldr_command, shell=True)
      

      【讨论】:

        【解决方案4】:

        Excel 还附带 ODBC 支持,因此假设您有驱动程序,您可以直接从 Excel 泵入 Oracle。也就是说,任何涉及转换内存中的大量数据(来自 Excel 内部使用的任何数据)然后将其传递到数据库的任何操作都可能比可以优化以使用更少内存的专用批量操作的性能更低。通过 Python 只是为任务添加了另一层(Excel 到 Python 到 Oracle),尽管可以将其设置为使用流。

        【讨论】:

          【解决方案5】:

          如上一个答案中所述,自动将 XLSX 导出为 CSV。但是,与其调用 sqlldr 脚本,不如创建一个使用您的 sqlldr 代码的外部表。每次选择表格时,它都会从 CSV 加载您的表格。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-09-01
            • 2016-10-03
            • 1970-01-01
            • 1970-01-01
            • 2014-07-09
            • 2021-10-02
            • 2020-04-03
            • 2023-03-12
            相关资源
            最近更新 更多