我试图提高Azure SQL中的摄取速度。即使我使用SQLAlchemy连接池,在一定数量的线程之后速度也不会增加,并且每秒大约停留700次。
Azure SQL显示50%的资源利用率。代码在Azure中运行,因此网络不应成为问题。
有没有办法提高速度?
import pyodbc
from sqlalchemy.engine import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
def connect():
return pyodbc.connect('....')
engine = create_engine('mssql+pyodbc://', creator=connect, pool_recycle=20, pool_size=128, pool_timeout=30)
session_factory = sessionmaker(bind=engine)
def process_entry(i):
session = scoped_session(session_factory)
# skipping logic for computing vec, name1, name2
# vec - list of floats, name1, name2 - strings
vec = [55.0, 33.2, 22.3, 44.5]
name1 = 'foo'
name2 = 'bar'
for j, score in enumerate(vec):
parms = {'name1': name1, 'name2': name2, 'score': score }
try:
session.execute('INSERT INTO sometbl (name1, name2, score) VALUES (:name1, :name2, :score)', parms)
session.commit()
except Exception as e:
print(e)
fs = []
pool = ThreadPoolExecutor(max_workers=128)
for i in range(0, N):
future = pool.submit(process_entry, i)
fs.append(future)
concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)
答案 0 :(得分:1)
commit()
每行强制等待将行保存到日志文件中,并可能保存为辅助副本。而是每N行提交一次。类似的东西:
rn = 0
for j, score in enumerate(vec):
parms = {'name1': name1, 'name2': name2, 'score': score }
try:
session.execute('INSERT INTO sometbl (name1, name2, score) VALUES (:name1, :name2, :score)', parms)
rn = rn + 1
if rn%100 == 0:
session.commit()
except Exception as e:
print(e)
session.commit()
如果要更快地加载数据,可以发送包含批量数据的JSON文档并解析并使用SQL Server中的OPENJSON函数批量插入它们。还有一些特殊的批量加载API,但是从athon中无法轻松访问这些API。
您也可能在适度数量的工作人员中达到最大吞吐量。除非您的表格为Memory Optimized,否则您的插入内容可能需要协调对共享资源的访问,例如锁定BTree中的主要页面或二级索引中的行锁定。
您目前拥有的高并发性可能只是(部分)补偿了当前的每行提交策略。
答案 1 :(得分:0)
根据数据库大小,您可以考虑在此IO密集型工作负载期间扩展到高级层以加快速度,一旦完成,您可以考虑缩放到原始层。
您也可以考虑使用批处理来提高性能。 Here您将找到如何使用批处理和其他策略来改进插件性能,如SqlBulkCopy,UpdateBatchSize等。
要获得最快的插入性能,请遵循以下一般准则,但测试您的方案: