Azure数据库提取速度

时间:2018-06-13 18:57:56

标签: python sql-server azure azure-sql-database

我试图提高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)

2 个答案:

答案 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等。

要获得最快的插入性能,请遵循以下一般准则,但测试您的方案:

  • For< 100行,使用单个参数化INSERT命令。
  • For< 1000行,使用表值参数。
  • 对于> = 1000行,请使用SqlBulkCopy。