我实现了一个python脚本,用这个方案将数百万个文档(由.netweb应用程序生成,所有内容都放在一个目录中)分成子文件夹:year/month/batch,因为这些文档来自的所有任务最初都被分为批处理。
我的python脚本对sqlserver2014执行查询,其中包含每个文档所需的所有数据,尤其是创建文档的月份和年份。然后它使用shutil模块来移动pdf。因此,我首先执行第一个查询以获取给定月份和年份的批次列表:queryBatches = '''SELECT DISTINCT IDBATCH
FROM [DBNAME].[dbo].[WORKS]
WHERE YEAR(DATETIMEWORK)={} AND MONTH(DATETIMEWORK)={}'''.format(year, month)
然后我表演:
^{pr2}$
根据PYMSSQL使用文档,其记录被收集到一个游标中。所以我继续说:IDWorksUpdate = []
row = cursor.fetchone()
while row:
if moveDocument(...):
IDWorksUpdate.append(row[0])
row = cursor.fetchone()
最后,当循环结束时,在IDWorksUpdate中,我将成功地将文档成功地移动到子文件夹中的所有作品包。所以,我关闭光标和连接,并实例化新的连接。
最后我表演:subquery = '('+', '.join(str(x) for x in IDWorksUpdate)+')'
query = '''UPDATE [DBNAME].[dbo].[WORKS] SET NAMEDOCUMENT = \'/{}/{}/{}/\'+NAMEDOCUMENT WHERE IDWORK IN {}'''.format(year,month,idbatch,subquery)
newConn = pymssql.connect(server='localhost', database='DBNAME')
newCursor = newConn.cursor()
try:
newCursor.execute(query)
newConn.commit()
except:
newConn.rollback()
log.write('Error on updating documents names in database of works {}/{} of batch {}'.format(year,month,idbatch))
finally:
newCursor.close()
del newCursor
newConn.close()
今天早上,我看到只有几个批次的updatequery在数据库中执行失败,即使文档被正确地移到了子目录中。
该批处理有55000多个文档要移动,所以可能是IDWorksUpdate溢出,这有助于错误地创建最终更新查询?我以为55000不是一个很大的整数列表。问题是在PYMSSQL中,我们不能一次有多个连接/游标到同一个数据库,所以我不能在移动相应文件时更新记录。所以我想创建一个文档被正确移动的作品的pk列表,最后用一个新的连接/光标更新它们。会发生什么事?我做错了吗?在
更新
我刚刚编写了一个简单的脚本来重现将要执行的查询以更新记录,这是我从SQL Server得到的错误:The query processor ran out of internal resources and could not produce a query plan. This is a rare event and only expected for extremely complex queries or queries that reference a very large number of tables or partitions. Please simplify the query. If you believe you have received this message in error, contact Customer Support Services for more information.
以下是查询:UPDATE [DBNAME].[dbo].[WORKS] SET NAMEDOCUMENT = '/2016/12/1484/'+NAMEDOCUMENT WHERE IDWORK IN (list of 55157 PKs)
事实上,这个表非常大(大约有1400万条记录)。但是我需要这个PKs列表,因为只有文档被正确处理和移动的任务才能被更新。我不能简单地跑:UPDATE [DBNAME].[dbo].[WORKS] SET NAMEDOCUMENT = '/2016/12/1484/'+NAMEDOCUMENT WHERE YEAR(DATETIMEWORK)=2016 and
MONTH(DATETIMEWORK)=12 and IDBATCH=1484
这是因为我们的服务器受到了加密锁的攻击,我必须只处理和移动仍然存在的文档,等待其他文档被释放。
我应该把这些字符串分成子列表吗?怎样?在
更新2
似乎以下是一个解决方案:我将pk列表分成10000个块(一个完全实验性的数字),然后执行尽可能多的查询,每个块都有一个块作为子查询。在def updateDB(listID, y, m, b, log):
newConn = pymssql.connect(server='localhost', database='DBNAME')
newCursor = newConn.cursor()
if len(listID) <= 10000:
subquery = '('+', '.join(str(x) for x in listID)+')'
query = '''UPDATE [DBNAME].[dbo].[WORKS] SET NAMEDOCUMENT= \'/{}/{}/{}/\'+NAMEDOCUMENT WHERE IDWORKIN {}'''.format(y,m,b,subquery)
try:
newCursor.execute(query)
newConn.commit()
except:
newConn.rollback()
log.write('...')
log.write('\n\n')
finally:
newCursor.close()
del newCursor
newConn.close()
else:
chunksPK = [listID[i:i + 10000] for i in xrange(0, len(listID), 10000)]
for sublistPK in chunksPK:
subquery = '('+', '.join(str(x) for x in sublistPK)+')'
query = '''UPDATE [DBNAME].[dbo].[WORKS] SET NAMEDOCUMENT= \'/{}/{}/{}/\'+NAMEDOCUMENT WHERE IDWORK IN {}'''.format(y,m,b,subquery)
try:
newCursor.execute(query)
newConn.commit()
except:
newConn.rollback()
log.write('Could not execute partial {}'.format(query))
log.write('\n\n')
newCursor.close()
del newCursor
newConn.close()
这是一个好的/安全的解决方案吗?在