何千もの単語はデモほど深くはありません。私の知る限り、PythonのMySQLとsqliteはどちらもexecutemanyを使用して大量のデータをバッチで挿入でき、効率は基本的に通常の挿入よりも桁違いに向上しています。
executemanyを使用する利点
効率的
自分でテストしました。同じ10,000を超えるデータの場合、通常の挿入には54.5秒、実行には0.22秒かかります。効率についてはこれ以上詳しく説明しません。
ただし、SQLは少し異なります。SQLiteは%s、%dなどの代わりにプレースホルダーとして使用しますか?正しい方法の例は次のとおりです。
sql = 'insert into filelist (pkgKey, dirname, filenames, filetypes) values (?, ?, ?, ?);'
import sqlite3
class DbOperate(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super(DbOperate, cls).__new__(cls)
return cls._instance
def __init__(self, db_name):
self.db_name = db_name
self.connect = sqlite3.connect(self.db_name)
self.cursor = self.connect.cursor()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.connect.close()
def execute_sql(self, sql):
try:
self.cursor.execute(sql)
self.connect.commit()
except Exception as e:
self.connect.rollback()
def executemany_sql(self, sql, data_list):
# example:
# sql = 'insert into filelist (pkgKey, dirname, filenames, filetypes) values (?, ?, ?, ?);'
# data_list = [(1, '/etc/sysconfig', 'openshift_option', 'f'), (1, '/usr/share/doc', 'adb-utils-1.6', 'd')]
try:
self.cursor.executemany(sql, data_list)
self.connect.commit()
except Exception as e:
self.connect.rollback()
raise Exception("executemany failed")
sqlite_path = "***.sqlite"
with DbOperate(sqlite_path) as db:
t1 = time.clock()
sql = 'insert into filelist (pkgKey, dirname, filenames, filetypes) values (?, ?, ?, ?);'
data_list = [(1, '/etc/sysconfig', 'openshift_option', 'f'), (1, '/usr/share/doc', 'adb-utils-1.6', 'd')]
db.executemany_sql(sql, data_list)
t2 = time.clock()
print('insert data into filelist cost %s seconds' % (t2 - t1))
print('success insert data into filelist with %s' % sqlite_path)
特殊文字の影響を受けません
前に1つ挿入するとき、私は次のようにそれをしました:
with DbOperate(sqlite_path) as db:
t1 = time.clock()
for item in packages:
insert_data = f'insert into packages values {item};'
insert_data = insert_data.replace('None', 'null')
print(insert_data)
db.execute_sql(insert_data)
t2 = time.clock()
その結果、一部のフィールドには常に一重引用符やエスケープ文字などの特殊文字が多数含まれるため、SQLステートメントを直接スプライシングすると、さまざまな理由でSQLステートメントがSQLite構文に適合しなくなります。データは挿入時に常に報告されます。間違って、それは私を非常に苛立たせました。executemanyを使用する場合、そのようなエラーはありません。実際には少し混乱しています。executemanyがそれに応じてパラメーターを渡すためかもしれません。
Traceback (most recent call last):
File "C:/Users/lukaiyi/insight-tool/test.py", line 144, in <module>
insert_data_sqlite(sqlite_list, filelist, packages)
File "C:/Users/lukaiyi/insight-tool/test.py", line 42, in insert_data_sqlite
db.execute_sql(insert_data)
File "C:\Users\lukaiyi\insight-tool\src\tool\utils.py", line 92, in execute_sql
self.cursor.execute(sql)
sqlite3.OperationalError: near "s": syntax error