【问题标题】:Run Oracle update statements in a batch mode以批处理模式运行 Oracle 更新语句
【发布时间】:2010-10-26 00:04:59
【问题描述】:

我需要运行几个相对简单的 SQL 更新语句来更新包含 1440 万行的 Oracle 表中的单个列。一条语句运行一个用 Java 编写的函数,当我对所有 1440 万行进行更新时,JVM 内存不足。

您是否编写了一种批处理 PL/SQL 例程,可以将这个简单的更新分解为每批 10K 条记录的集合?我知道如果我可以在一堆记录之后提交我的更新,它会更快,而且我不会耗尽内存。我确信有一种简单的方法可以使用 FOR looprow_num 来做到这一点,但我没有取得太大进展。

这是我需要为每批 n 条记录运行的两条语句:

第一个:

 update vr_location l set l.usps_address=(
   select mylib.string_utils.remove_duplicate_whitespace(
   house_number || ' ' || pre_street_direction || ' ' || street_name || ' ' || 
   street_description || ' ' || post_street_direction)
 from vr_address a where a.address_pk=l.address_pk);

秒:

update vr_location set usps_address = mylib.usaddress_utils.parse_address(usps_address);

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    执行初始选择以检索某种分组属性,以便最终获得具有所需行数的组。尝试使用分组子句,例如邮政编码的最后三位数字或半随机的东西。

    遍历分组子句,使用该子句作为参数来限制每个更新语句所针对的行。在每次迭代结束时提交。

    【讨论】:

    • 如果我们能看到 vr_location 中的列,我们或许可以提出一些建议。
    • VR_LOCATION 中的列确实包含一个 zip_co 列,它是一个返回到 zip_code 表的 FK。我将接受 stili 的建议并使用它来获取数据子集。与其说是试图在一个基于集合的语句中完成所有事情,不如说是让我的 JVM 一次处理 20-30K 行而不会崩溃。
    【解决方案2】:

    您(或您的 DBA)应适当调整 UNDO 的大小并将其作为单个 SQL 事务执行

    优点是:

    • 发生这种情况时读取表的一致性
    • 您保留在出现故障时回滚事务的能力

    如果您在某种加载环境中您不关心其中任何一个,那么使用 CTAS(创建表作为选择)使用修改后的值创建一个新表,构建索引、约束等然后交换表名。如今,1400 万行已经不是那么大了。

    【讨论】:

    • 听起来不像是UNDO问题,但是java存储过程没有释放内存。
    • 是的,JVM 正在扼杀我的记忆。在具有 4GB RAM 的笔记本电脑上工作,其中一半由 oracle 使用,其余部分在 OS、Java 等之间分配。但我已经向我的 DBA 提到了这一点。此外,这不是生产:我必须将 exp/imp 的一些数据添加到生产表中。
    【解决方案3】:

    嗯,我必须完成一些事情,所以我接受了你的建议,然后做了一点 Python 来完成它。我最终使用 cx_Oracle 来很好地控制交易。显然 PL/SQL 会更好,但我不知道。 Python 是我的新锤子,一切都是钉子!

    #!/usr/bin/env python
    import csv
    import time
    import cx_Oracle
    
    # Parses USPS addresses from voter addresses
    # and inserts them into VR_LOCATION table ready
    # for geocoding. Does batches by zipcode
    def LoadZips():
        zipcodes = []
        zips = open('OH_ZIP_CODES.txt','r')
        for line in zips:
            zip = line[0:5]
            if zip not in zipcodes:
                zipcodes.append(zip)
        zips.close()
        return zipcodes
    
    def UpdateAddresses(ziplist):
        counter = 1
        total = len(ziplist)
    
        for zipcode in ziplist:
            orcl = cx_Oracle.connect('voter/voter@oracle')
            curs = orcl.cursor()
            countsql = "select count(*) from vr_location where zip_co = '%s'" % zipcode
            concatsql = """update vr_location l set l.usps_address=(
                        select mizar.string_utils.remove_duplicate_whitespace(
                            house_number
                            ||' '||pre_street_direction
                            ||' '||street_name
                            ||' '||street_description
                            ||' '||post_street_direction)
                        from vr_address a where a.address_pk = l.address_pk)
                    where zip_co = '%s'""" % zipcode
            parsesql = """update vr_location set usps_address =  mizar.usaddress_utils.parse_address(usps_address)
                    where zip_co = '%s'""" % zipcode
            curs.execute(countsql)
    
            records_affected = curs.fetchone()[0]
        if records_affected == 0:
            print "No records for zipcode %s" % zipcode
            counter += 1 
            continue
    
        print "[%s] %s of %s: %s addresses" % (zipcode, counter, total, records_affected)
        curs.execute(concatsql)
        orcl.commit()
        curs.execute(parsesql)
        orcl.commit()
        curs.close()
        counter += 1 
    
        # Uncomment this to debug - just steps through X zipcodes      
        #if counter == 3:
        #    print "Cleaning up..."
        #    break
    
    
    if __name__ == "__main__":
        start = time.clock()
        zipcodes = LoadZips()
        print "Processing addresses in %s zip codes" % len(zipcodes)
        UpdateAddresses(zipcodes)
    

    Blog post on the topic

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2013-01-18
      • 1970-01-01
      相关资源
      最近更新 更多