使用 python 将大量 XLS 数据加载到 Oracle

loading huge XLS data into Oracle using python

我有一个超过 300 万条记录的 XLS 文件,我需要使用 python 2.7.

将其转储到 Oracle 12C DB(直接转储)中

我正在使用 Cx_Oracle python 包建立与 Oracle 的连接,但是读取和转储 XLS(使用 openpyxl pckg)非常慢并且 thousands/million 记录的性能下降。

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

  1. 我已经尝试过批量加载,通过读取数组中的所有值然后使用游标准备(使用绑定变量)转储它并且游标 fetchmany.This 不能很好地处理巨大的数据.

  2. 以这种方式迭代加载数据 fetched.Even 存在性能问题。

我可以部署哪些选项和 techniques/packages 作为最佳实践,以将此数据量从 XLS 加载到 Oracle DB?建议通过脚本加载此数据量还是我必须使用 ETL工具 ? 截至目前,我只能通过 python 脚本进行选择,所以请回答前者

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

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

基本上,对于大容量数据,任何语言都会强调 I/O, 除了 C。最好的方法是使用数据库供应商提供的原生 tools/utilities。 对于 oracle,正确的选择是 SQL Loader。

参考此 link 快速教程 http://www.thegeekstuff.com/2012/06/oracle-sqlldr/

给你…运行 SQL 加载程序并返回 return 代码、输出和错误的示例代码

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()

以下是所有步骤:加载 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)

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