我正在生成( MySQL格式的) SQL语句,并将其写入文件以创建10,000个表。每个表包含5个列,每个列中有150万行数据。我使用regex和faker模块生成了这些数据。因此,我有一个10,000的循环(每个create表都有一个语句),在这个循环中,我有一个150万的循环(将插入数据行到创建的每个表中)。
代码运行正常,但extremely运行缓慢。有什么办法能让这个动作跑得更快吗?
import rstr
import random
from faker import Faker
import time
fake = Faker()
name = ['Name', 'Person_Name', 'Customer_Name', 'Employee_Name', 'Contact_Name', 'CustName', 'EmpName']
ssn = ['SSN', 'Social_Security_Number', 'National_Identification_Number', 'NID', 'US_SSN', 'Social_Number', 'Social_Security_No', 'Social_Security_Num', 'Customer_Social_Security Number', 'Employee_Social_Security_Number']
address = ['Address', 'Customer_Location_Details', 'Employee_Address_Details', 'Address_Det.', 'Add_Line_1', 'Add_Line_2', 'Address_Line_1', 'Address_Line_2']
dob = ['DOB', 'Date_Of_Birth', 'Birth_Date', 'V_VLD_BRTH_DT', 'DAY_OF_BRTH', 'DT_OF_BIRTH']
phone = ['Phone_Number', 'Contact_Number', 'Office_Phone', 'Residential_phone', 'Contact_Phone']
ssn1='(?!000|.+0{4})(?:\d{9})'
ssn2='(?!000|.+0{4})(\d{3}-\d{2}-\d{4})'
sList=[ssn1,ssn2]
db1='^(0[1-9]|[12][0-9]|3[01])[/](0[1-9]|1[012])[/](19)\d\d
db2='^(19)\d\d$[.](0[1-9]|1[012])[.](0[1-9]|[12][0-9]|3[01])'
db3='^(19)\d\d$[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])'
db4='^(0[1-9]|[12][0-9]|3[01])[-](0[1-9]|1[012])[-](19)\d\d
db5='^(0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.]\d\d
dbList=[db1,db2, db3, db4, db5]
p1='1[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p2='[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p3='001[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p4='[(][\d]{3}[)][ ]?[\d]{3}-[\d]{4}'
p5='\+1[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p6='(\d{3}\d{3}\d{4})'
p7='[2-9][0-8][0-9][-][2-9][0-9]{2}[-][0-9]{4}'
pList=[p1, p2, p3, p4, p5, p6, p7]
tables=10001
rows=1500001
with open("D:\Output.sql", "a") as text_file:
count = 0
for i in range(1,tables):
a=[]
b=[]
j=str(i)
x=f'Tab_{i}'
#a.append(random.choice(name)+'_'+j)
#a.append(random.choice(ssn)+'_'+j)
#a.append(random.choice(address)+'_'+j)
#a.append(random.choice(dob)+'_'+j)
#a.append(random.choice(phone)+'_'+j)
a.extend(f'{random.choice(n)}_{j}' for n in (name, ssn, address, dob, phone))
text_file.write(f"create table Python_test.{x}({a[0]} VARCHAR(255),{a[1]} VARCHAR(255),{a[2]} VARCHAR(255),{a[3]} VARCHAR(255),{a[4]} VARCHAR(255));\n")
start = time.time()
for j in range(1,rows):
text_file.write(f"insert into {x}({a[0]},{a[1]},{a[2]},{a[3]},{a[4]}) values ('{fake.name()}','{rstr.xeger(random.choice(sList))}','{fake.address()}','{rstr.xeger(random.choice(dbList))}','{rstr.xeger(random.choice(pList))}');\n")
print(time.time() - start)
text_file.write('\n')
count+=1
print(count)发布于 2019-08-30 00:54:38
with中使用open
...so,无论是否存在任何可能的异常,都可以保证您的文件关闭。
所以这样的事情:
x='Tab_'+str(i)转成
x = f'Tab_{i}'a.append(random.choice(name)+'_'+str(i))
a.append(random.choice(ssn)+'_'+str(i))
a.append(random.choice(address)+'_'+str(i))
a.append(random.choice(dob)+'_'+str(i))
a.append(random.choice(phone)+'_'+str(i))可以是
a.extend(f'{random.choice(n)}_{i}' for n in (name, ssn, address, dob, phone))除非您对数据的来源、安全性和有效性很有信心,否则构建一个字符串并将其作为可执行SQL发送是数据库安全性的敌人之一。这就是准备好的陈述的意义所在。目前还不清楚您需要什么样的SQL,因此也不清楚您需要哪一个库。
count=count+1可以是
count += 1发布于 2019-08-30 01:13:47
您应该在编写的每个模块、类和函数的开头包含一个docstring。这将使文档能够识别您的代码应该做什么。
with open诉file = open目前,您使用text_file = open("D:\Output.sql", "a", encoding="utf-8")打开文件,并使用text_file.close()手动关闭它。您可以通过使用with open(...) as ...:打开文件来避免这样做。这使您可以使用该文件,并且一旦完成并超出范围,就可以继续编写程序。“但是等等,关闭文件怎么样?”当您使用with时,一旦您超出了with的范围,它就会自动关闭。
for i in range(1,10001): ...
for j in range(1,1500001): ...乍一看,我不知道这些数字应该代表什么。您应该将这些数字分配给变量,并使用这些变量。这使得代码更简洁,更易于维护。如果您想更改表的数量或人数,该怎么办?您需要找到这个神奇数字的每个实例(如果您不止一次使用它)并更改它。将它分配给变量可以解决这个问题,因为您只需更改变量的值即可。
f""text_file.write('create table Python_test.'+x+'('+a[0]+' VARCHAR(255),'+a[1]+' VARCHAR(255),'+a[2]+' VARCHAR(255),'+a[3]+' VARCHAR(255),'+a[4]+' VARCHAR(255));\n')
这读起来很痛。所有的+都将字符串分开,因此很难知道整个字符串是什么。我的解决方案是使用f"..."。这允许您直接将变量合并到字符串中,而不必使用+...+,也可以避免(如果存在) +str(...)+,这对我来说非常难看。
有一个重新定义的列表与固定位置的人的属性是混乱的。相反,您可以生成一个包含Person实例的列表,并且可以在将其合并到SQL字符串中时访问它们的属性。
用于未使用循环变量的
_ 在循环中不使用变量时,例如:
for i in range(5):
print("Hi!")您应该使用_。这清楚地表明,不需要用于循环的变量,应该忽略它。
我编写了一些帮助函数,用于在代码中生成一些随机值。在代码中使用助手函数确实可以帮助您,因为您不必将所有内容都塞进一个函数中。
免责声明:我不知道您在向表中插入数据时要做什么,所以我留下了空白。fake和rstr没有定义/没有显示在您的程序中也没有帮助。
Updated代码
"""
Module Docstring
A description of your program goes here
"""
import random
class Person():
"""
Class to store properties of Person
"""
def __init__(self, name, ssn, address, dob, phone):
self.name = name
self.ssn = ssn
self.address = address
self.dob = dob
self.phone = phone
def generate_ssn():
"""
Returns a randomly generated SSN
"""
return f"{random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(1000, 9999)}"
def generate_dob():
"""
Returns a randomly generated address in format MM/DD/YYYY
"""
return f"{random.randint(1, 12)}/{random.randint(1, 31)}/{random.randint(1919, 2019)}"
def generate_phone():
"""
Returns a randomly generated phone number
"""
return f"{random.randint(100, 999)}-{random.randint(100, 999)}-{random.randint(1000, 9999)}"
def generate_sql_script(num_people, num_tables, output_file):
"""
Generates an SQL script for inserting people into tables
"""
with open(output_file, "a") as out_file:
people = []
count = 0
for i in range(1, num_people):
people.append(Person(f"John_{i}",
generate_ssn(),
f"123 Main St_{i}",
generate_dob(),
generate_phone())
)
random_person = random.choice(people)
table = f"Tab_{i}"
out_file.write(f'CREATE TABLE Python_test.{table}({random_person.name} VARCHAR(255), {random_person.ssn} VARCHAR(255), {random_person.address} VARCHAR(255), {random_person.dob} VARCHAR(255), {random_person.phone} VARCHAR(255)')
for _ in range(1, num_tables):
#Couldn't understand what this is doing with `fake` and `rstr`
pass
out_file.write('\n')
count += 1
print(count)https://codereview.stackexchange.com/questions/227129
复制相似问题