# -*- coding: UTF-8 -*-

import multiprocessing  #多进程的包

from pprint import pprint   #pprint是可以用来很好的显示列表

import cx_Oracle      #连接oracle的组件

from time import clock   #计时用,可以用来检测程序运行时间

import os

os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'     #使得所有的输出文本支持UTF-8

 

#start=clock()    #时间开始

 

zero=[]       #设置全局变量存放所有的表名用(这个是单纯的取出数据放在数组中)

data=[]       #设置全局变量存放所有的数据用(这个是为了构造出我们要的那种形式的数组)

structure=[]  #设置全局变量存放所有表的列名用(这个是为了构造出我们要的那种形式的数组)

zero_many=[]  #设置全局变量存放所有的表名用(这个是为了构造出我们要的那种形式的数组)

 

def first():  #这个函数完成后的结果是在第二个数据库上创建完了所有对应用户的表,构造完成上面的data,structure,zero_many

    global zero

    global data

    global structure

    global zero_many             #这些设置global是为了能在函数中改变全局变量使得全局变量一直保存我们想要的数据

 

 

    # 查询数据库1当前用户下所有的表,把查询记录保存在zero中

    sql2 = "select table_name from user_tables"

    cha0.execute(sql2)

    zero = cha0.fetchall()

 

    for i in range(len(zero)):  #按照表名的循环,循环体中相当于你对于一张指定的表在操作

        #查询表的创建语句,并在第二个数据库上创建对应表

        sql = "select dbms_metadata.get_ddl('TABLE','" + zero[i][0] + "') from dual"

        cha0.execute(sql)

        one = cha0.fetchall()

        cha1.execute(one[0][0].read())   #这里取one中数据用.read()的形式是因为从dual中取出的是BLOB类型数据,.read()可以转化为str类型

 

 

        # 利用数据库一中当前表名进行数据查询,结果保存在two中

        sql3 = "select * from " + zero[i][0]

        print sql3

        cha0.execute(sql3)

        two = cha0.fetchall()

        #pprint(two)

 

        # 利用数据库一中当前表名执行当前表的列名查询,结果保存在three中

        sql0 = "select COLUMN_NAME,DATA_TYPE,DATA_LENGTH from user_tab_columns where table_name='" + zero[i][0] + "' order by column_id"

        cha0.execute(sql0)

        three = cha0.fetchall()

        #print three

 

        #以下就是构造了data,structure,zero_many我们想要的数组形式

        e=len(two)/4       #可以看到这里的数字4,这个4表示我的想法是将所有的数据切割4份,虽然切不匀,但是可以让多进程发挥作用,

        r=len(two)%4       #你要是要让每个进程都均匀操作相同数据量就把数字设置大点,但是数字是几,你的硬解析次数就乘几倍

        q=0                #q是用来确定取表中数据范围的,每次取出25%数据后,就让下次取数据到这次的25%之后开始

 

        #以下两个if的作用是,e>=1筛选出数据量大于4的情况,e==0 and r>0筛选出数据量小于4的情况,而空表则没有操作

        if e >= 1:

            for d in range(4):

                if q / 3 == e:         #这里q/3用来判断是否是切割的最后一份数据了

                    a=[]               #a的初始化,因为每次a只用来取出当前two中25%的数据量,不初始化循环后a中的数据会和two一样多

                    for k in range(q, q + e + r):   #切割4份,当到第四份的时候不能匀切,所以第四份加上切剩下的部分,当然你要切N份也是一样的道理

                        a.append(two[k])     #将保存当前表所有数据的two拆开一层数组,取出25%左右放入a这个数组中重新包装

                    data.append(a)           #将当前a中相当于当前表25%左右的据保存在全局变量的data中

 

                if q / 3 < e:          #同上

                    a=[]               #同上

                    for k in range(q, q + e):    #切割4份,最后一份之前都是匀切,所以都是q~q+e

                        a.append(two[k])    #同上

                    data.append(a)          #同上

                    q = q + e               #这里由于不是最后一份,所以让q增大

 

            structure.append(three)        #列名重复制作4份,为了和切割后的数据数组data对应

            structure.append(three)

            structure.append(three)

            structure.append(three)

 

            zero_many.append(zero[i][0])   #表名重复制作4份,为了和切割后的数据数组data对应

            zero_many.append(zero[i][0])

            zero_many.append(zero[i][0])

            zero_many.append(zero[i][0])

 

        if e == 0 and r>0:                 #因为连4条数据都没有,所以直接让一条进程去做

            data.append(two)

            structure.append(three)

            zero_many.append(zero[i][0])

    #pprint(structure)

 

 

 

def insert(y,zero_many,structure,data):     #这里可以看到insert操作需要所有的表名zero_many,所有的表结构structure,所有的数据data,y是用来指定我取哪条数据的

    conn2 = cx_Oracle.connect("god/god@192.168.214.147:1521/TEST")    #创建数据库2的连接

    cha2 = conn2.cursor()                                             #创建数据库2的游标

 

    # 创建列表m[],b[],m用来保存structure中表的结构

    m = []

    b = []

    #pprint(data[y])

    # for循环开始

    for v in range(len(structure[y])):

        m.append(structure[y][v][0])

        m.append(',')

        b.append(':' + str(v))

        b.append(',')

    # for循环结束

 

    # 将m构造成['列名1','逗号','列名2'.....]

    # 将b构造成[':0','逗号',':1'......]

    del m[len(m) - 1]    #去掉最后的逗号

    del b[len(b) - 1]    #去掉最后的逗号

 

    # 将m,b都转化成字符串

    # m变为 列名1,列名2,列名3……

    # b变为 :0,:1,:2…..

    n = "".join(m)

    x = "".join(b)

 

    # 利用zero中的表名,构造出的n,x来制订出当前表的插入数据的准备语句

    sql4 = "INSERT INTO " + zero_many[y] + "(" + n + ") VALUES (" + x + ")"

    #print sql4

    # 准备语句prepare,绑定变量的批量执行语句executemany,不要忘记commit

    cha2.prepare(sql4)

    cha2.executemany(None, data[y])

    conn2.commit()

    cha2.close()

    conn2.close()

 

 

if __name__ == "__main__":      #主函数执行开始

    conn0 = cx_Oracle.connect("god/god@192.168.214.158:1521/TEST")   #创建数据库1的连接

    cha0 = conn0.cursor()                                            #创建数据库1的游标

    conn1 = cx_Oracle.connect("god/god@192.168.214.147:1521/TEST")   #创建数据库2的连接

    cha1 = conn1.cursor()                                            #创建数据库2的游标

 

    first()                                                          #执行first

    pool = multiprocessing.Pool(processes=3)                       #创建进程池,设置最多进程数为3

    #pprint(data)

    for vv in xrange(len(data)):                                     #按照data的数组长度循环

        pool.apply(insert, [vv,zero_many,structure,data])           #传入insert函数需要的所有的值,这里insert访问不到全局变量

 

    pool.close()                                                    #关闭进程池

    pool.join()                                                     #等待主程序结束

 

    cha1.close()                                                     #关闭数据库2的游标

    conn1.close()                                                    #关闭数据库2的连接

    cha0.close()                                                     #关闭数据库1的游标

    conn0.close()                                                    #关闭数据库1的连接

 

 

#end=clock()    #时间结束

#print(end-start)    #统计时间




Related posts

coded by nessus
分享:  DeliciousGReader鲜果豆瓣CSDN网摘
Trackback

no comment untill now

Add your comment now

无觅相关文章插件