PythonのSQLite3は、executemanyを使用してデータをバッチで挿入します

何千もの単語はデモほど深くはありません。私の知る限り、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

 

おすすめ

転載: blog.csdn.net/TomorrowAndTuture/article/details/113978649