Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.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 APSW(或SQLite3)在ExecuteMy上的插入速度非常慢_Python_Sqlite - Fatal编程技术网

Python APSW(或SQLite3)在ExecuteMy上的插入速度非常慢

Python APSW(或SQLite3)在ExecuteMy上的插入速度非常慢,python,sqlite,Python,Sqlite,在插入行时,我发现APSW(Python的SQLite解析器)存在以下问题 假设我的数据是data=[[1,2],[3,4]] APSW和SQLite3允许我执行以下操作: apsw.executemany("INERT INTO Table VALUES(?,?)", b) 或者我可以编写一些代码来执行以下操作: sql = "BEGIN TRANSACTION; INSERT INTO Table Values('1','2'); INERT INTO Table Values('3',

在插入行时,我发现APSW(Python的SQLite解析器)存在以下问题

假设我的数据是
data=[[1,2],[3,4]]

APSW和SQLite3允许我执行以下操作:

apsw.executemany("INERT INTO Table VALUES(?,?)", b)
或者我可以编写一些代码来执行以下操作:

sql = "BEGIN TRANSACTION; 
INSERT INTO Table Values('1','2');
INERT INTO Table Values('3','4');
COMMINT;"

apsw.execute(sql)
data
是一个长列表/数组/表时,第一种方法的性能比第二种方法慢得多(对于400行,它可能是20秒而不是1秒!)。我不明白为什么会这样,因为在所有SQLite Python教程中都显示了将数据添加到表中的方法


知道这里会发生什么吗?

多亏了Confuseh,我得到了以下答案:

执行:

apsw.execute("BEGIN TRANSACTION;")
apsw.executemany("INERT INTO Table VALUES(?,?)", b)
apsw.execute("COMMIT;")
这一过程大大加快了!这似乎是添加数据的正确方法(与使用我创建多个插入语句的方法相比)。

(披露:我是APSW的作者)。如果没有显式生效的事务,则SQLite会在每条语句的开头自动启动一个事务,并在每条语句的末尾结束。写事务是持久的——这意味着内容必须最终存储在存储器上,并调用fsync以确保它们能够在意外的电源或系统故障下生存。存储速度慢

在您的情况下,我建议将
一起使用,而不要使用BEGIN/COMMIT,因为它会在出现错误时自动回滚。这样可以确保数据插入要么完全发生,要么根本不发生。有关示例,请参见


当您插入大量数据时,您会发现性能更高。

谢谢您提出这个问题,当我将Sqlite与Python结合使用时,答案会帮助我。最后,我得到以下东西,希望它能帮助一些人:

当连接到sqlite数据库时,我们可以使用

con=sqlite3.connect(“:memory:”,隔离级别=None)
con=sqlite3.connect(“:memory:”)


当use-isolation\u-level=None时,它将使用自动提交模式,这会产生太多事务,并且变得太慢。这将有助于:

cur.execute("BEGIN TRANSACTION")
cur.executemany(....)
cur.execute("COMMIT")
如果使用
con=sqlite3.connect(“:memory:”)
cur.executemany(..)
将立即快速运行。

问题 对于
mysqlclient-python
/
pymysql
用户来说,如果他们希望
sqlite3
/
apsw
executemany
将其
惰性值重写为表值(?,)
为多行
INSERT
语句,则可能会产生混淆

例如,
mysqlclient-python
的docstring中包含以下内容:

此方法提高了多行插入和替换的性能。否则,它相当于使用execute()在参数上循环

Python stdlib的
sqlite3.Cursor.executemany
没有这种优化。它总是循环等价的。下面是如何演示它(除非你想读一些C,):

它打印:

CREATE TABLE tbl (x INTEGER, y INTEGER)
INSERT INTO tbl VALUES(0, 0)
INSERT INTO tbl VALUES(1, 1)
INSERT INTO tbl VALUES(2, 4)
INSERT INTO tbl VALUES(3, 9)
INSERT INTO tbl VALUES(4, 16)
解决方案 因此,您需要将这些
INSERT
s重写为多行(手动或,例如,使用)以保持自动提交模式(
isolation\u level=None
),或者在默认隐式提交模式下将
INSERT
s包装在事务中(一个事务中包含合理数量的
INSERT
s)。后者表示上述代码段的以下内容:

import sqlite3

conn = sqlite3.connect(':memory:')
conn.set_trace_callback(print)
conn.execute('CREATE TABLE tbl (x INTEGER, y INTEGER)')

with conn:
    conn.executemany('INSERT INTO tbl VALUES(?, ?)', [(i, i ** 2) for i in range(5)])
现在它打印:

CREATE TABLE tbl (x INTEGER, y INTEGER)
BEGIN 
INSERT INTO tbl VALUES(0, 0)
INSERT INTO tbl VALUES(1, 1)
INSERT INTO tbl VALUES(2, 4)
INSERT INTO tbl VALUES(3, 9)
INSERT INTO tbl VALUES(4, 16)
COMMIT

为了进一步提高SQLite中的大容量插入性能,我建议从开始。

事务比执行sql更快。您可以在第一个方法中执行相同的操作,方法是在
executemany
之前添加
aspw.execute(“开始事务”)
,在执行时添加
aspw.execute(“提交”)
done@Confuseh事实上,许多事务处理速度较慢,但是一个事务和事务中的大量插入仍然比没有事务的插入更快。Confuseh CL感谢您的回复和有趣的链接。希望这个帖子可以帮助那些有类似问题的人future@Confuseh在没有交易的情况下不可能有插入;如果没有显式的
BEGIN
/
COMMIT
,则每个语句都会有一个。您好,罗杰,非常感谢您的详细解释!不是每天都有开发人员在你每天使用的工具后面写在你的StackOverflow帖子上!!!!!
CREATE TABLE tbl (x INTEGER, y INTEGER)
BEGIN 
INSERT INTO tbl VALUES(0, 0)
INSERT INTO tbl VALUES(1, 1)
INSERT INTO tbl VALUES(2, 4)
INSERT INTO tbl VALUES(3, 9)
INSERT INTO tbl VALUES(4, 16)
COMMIT