Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用SQLAlchemy将记录更快地插入到表中_Python_Sql_Mysql_Sqlite_Sqlalchemy - Fatal编程技术网

Python 使用SQLAlchemy将记录更快地插入到表中

Python 使用SQLAlchemy将记录更快地插入到表中,python,sql,mysql,sqlite,sqlalchemy,Python,Sql,Mysql,Sqlite,Sqlalchemy,我正在解析日志并使用SQLAlchemy和Python将其插入MySQL或SQLite。现在,我打开了一个到DB的连接,当我在每一行上循环时,我会在解析后插入它(现在这只是一个大表,对SQL不是很有经验)。然后在循环完成后关闭连接。总结代码为: log_table = schema.Table('log_table', metadata, schema.Column('id', types.Integer, primary_key=True),

我正在解析日志并使用SQLAlchemy和Python将其插入MySQL或SQLite。现在,我打开了一个到DB的连接,当我在每一行上循环时,我会在解析后插入它(现在这只是一个大表,对SQL不是很有经验)。然后在循环完成后关闭连接。总结代码为:

log_table = schema.Table('log_table', metadata,
                         schema.Column('id', types.Integer, primary_key=True),
                         schema.Column('time', types.DateTime),
                         schema.Column('ip', types.String(length=15))
....
engine = create_engine(...)
metadata.bind = engine
connection = engine.connect()
....
for line in file_to_parse:
    m = line_regex.match(line)
    if m:
        fields = m.groupdict()
        pythonified = pythoninfy_log(fields) #Turn them into ints, datatimes, etc
        if use_sql:
            ins = log_table.insert(values=pythonified)
            connection.execute(ins)
            parsed += 1
我的两个问题是:

  • 有没有办法在这个基本框架内加速插入?可能有一个插入队列,一些插入线程,一些批量插入,等等
  • 当我使用MySQL时,大约120万条记录的插入时间是15分钟。对于SQLite,插入时间是一个多小时。db引擎之间的时间差似乎是正确的,还是意味着我做错了什么

如果不知道表引擎(MyISAM?InnoDB?)、模式和索引,就很难对正在使用的两个数据库之间的细节进行评论

然而,当像这样使用MySQL时,您可能会发现将数据写入临时文本文件,然后将其全部加载到数据库中要快得多。看起来需要运行执行此操作所需的SQL


此外,如果您死心塌地地一行一行地添加内容,并且每次都要重新创建表,则可以验证程序中的键约束,并仅在插入所有行后添加这些约束,节省数据库在每次插入时进行约束检查的时间。

您应该尝试的一件大事是围绕多个插入放置一个事务,因为将数据库提交到磁盘确实需要很长时间。您需要决定批处理级别,但粗略的第一次尝试是围绕整个批次包装事务。

为了实现批处理,我做了以下操作:

inserts = []
insert_every = 1000
for line in file_to_parse:
    m = line_regex.match(line)
    if m:
        fields = m.groupdict()
        if use_sql: #This uses Globals, Ick :-/
            inserts.append(pythonified)
            if (parsed % insert_every) == 0:
                connection.execute(log_table.insert(), inserts)
                inserts = []
            parsed += 1
if use_sql:
    if len(inserts) > 0:
        connection.execute(log_table.insert(), inserts)
这不使用事务,但以一种非常懒惰的方式,它允许我使用一个较小的示例将mysql后端的插入/解析阶段从约13秒变为约2秒。通过使用完整的示例,我将看到mysql和sqlite之间的区别

我找到了这个的基本信息

结果:
引擎:非分组插入时间(分钟):分组插入时间(分钟)
Sqlite:61:8
MySql:15:2.5


我没有刷新mysql和sqlite之间的缓存,这可能会有源文本文件,但我认为这不会是一个相对显著的区别。

所以我创建了一个ins对象数组,然后在数组满时执行?或者这不是你真正的意思?@Kyle:你需要用transaction=session.create_transaction()创建一个事务;然后稍后执行事务。提交。查看并向下滚动到“交易”标题。实际上不是我所做的,但这正是我所做并喜欢给人们打分的想法:-)。解释了我在下面所做的。“您可以验证程序中的关键约束,并仅在插入所有行后添加这些约束,从而节省数据库在每次插入时进行约束检查的时间。”您能为我详细介绍一下吗,那一部分我想不起来了:-P@Kyle如果没有一个表模式,很难给出细节。但是,例如,如果您有任何唯一索引,则该唯一性是表上的一个约束。每次插入一行时,数据库都会确保没有其他行与该行冲突。因为您只有一个表,所以您不必担心外键约束,但是如果您以后添加这些约束,这也适用于它们。我还应该声明,当我想知道如何加快它时,我的意思是,我应该做一些基本的事情,而不是让我获益匪浅吗(即,至少提高25%以上的时间速度)。速度在这里不是关键,我只是想知道我是否在以一种平淡的方式做一些事情,因为这对我来说是全新的。