- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
背景
我想使用python向sqlite插入100万条记录。我尝试了很多方法来改进它,但仍然不太满意。数据库使用0.23秒(下面的搜索pass
)将文件加载到内存,而SQLite使用1.77秒加载并插入到文件。
环境
英特尔酷睿i7-7700@3.6GHz
16GB内存
Micron 1100 256GB固态硬盘,Windows 10 x64
蟒蛇3.6.5明康达
sqlite3.2.6.0版
生成日期.py
我用与真实数据相同的格式生成100万个测试输入数据。
import time
start_time = time.time()
with open('input.ssv', 'w') as out:
symbols = ['AUDUSD','EURUSD','GBPUSD','NZDUSD','USDCAD','USDCHF','USDJPY','USDCNY','USDHKD']
lines = []
for i in range(0,1*1000*1000):
q1, r1, q2, r2 = i//100000, i%100000, (i+1)//100000, (i+1)%100000
line = '{} {}.{:05d} {}.{:05d}'.format(symbols[i%len(symbols)], q1, r1, q2, r2)
lines.append(line)
out.write('\n'.join(lines))
print(time.time()-start_time, i)
AUDUSD 0.00000 0.00001
EURUSD 0.00001 0.00002
GBPUSD 0.00002 0.00003
NZDUSD 0.00003 0.00004
USDCAD 0.00004 0.00005
...
USDCHF 9.99995 9.99996
USDJPY 9.99996 9.99997
USDCNY 9.99997 9.99998
USDHKD 9.99998 9.99999
AUDUSD 9.99999 10.00000
// total 1 million of lines, taken 1.38 second for Python code to generate to disk
import time
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
elapsed = time.time()-self.start
print('Imported in {:.2f} seconds or {:.0f} per second'.format(elapsed, 1*1000*1000/elapsed))
with Timer() as t:
with open('input.ssv', 'r') as infile:
infile.read()
with open('input.ssv', 'r') as infile:
infile.read()
with open('input.ssv', 'r') as infile:
with open('output.ssv', 'w') as outfile:
outfile.write(infile.read()) // insert here
with open('input.ssv', 'r') as infile:
lines = infile.read().splitlines()
for line in lines:
pass # do insert here
outfile.write(line)
tokens = line.split()
sym, bid, ask = tokens[0], float(tokens[1]), float(tokens[2])
outfile.write('{} {:.5f} {%.5f}\n'.format(sym, bid, ask)) // real insert here
conn = sqlite3.connect('example.db', isolation_level=None)
c.execute("INSERT INTO stocks VALUES ('{}',{:.5f},{:.5f})".format(sym,bid,ask))
conn = sqlite3.connect('example.db', isolation_level=’DEFERRED’) # default
c.execute("INSERT INTO stocks VALUES ('{}',{:.5f},{:.5f})".format(sym,bid,ask))
BEGIN
、
BEGIN TRANSACTION
或
BEGIN DEFERRED TRANSACTION
相同,而不是
BEGIN IMMEDIATE
或
BEGIN EXCLUSIVE
。
c.executemany("INSERT INTO stocks VALUES (?,?,?)", [(sym,bid,ask)])
EXTRA
或
FULL
时,电源故障会损坏数据库文件当我们能够保证电源和操作系统的正常运行时,我们可以将synchronous设置为
OFF
,这样在数据传输到操作系统层之后就不会同步。
conn = sqlite3.connect('example.db', isolation_level='DEFERRED')
c = conn.cursor()
c.execute('''PRAGMA synchronous = OFF''')
journal_mode
转换为
off
以便完全禁用回滚日志,并禁用原子提交和回滚功能。
conn = sqlite3.connect('example.db', isolation_level='DEFERRED')
c = conn.cursor()
c.execute('''PRAGMA synchronous = OFF''')
c.execute('''PRAGMA journal_mode = OFF''')
conn = sqlite3.connect(":memory:")
tokens = line.split()
c.executemany("INSERT INTO stocks VALUES (?,?,?)", [(tokens[0], float(tokens[1]), float(tokens[2]))])
line.split()[1]
变成
line[7:14]
c.executemany("INSERT INTO stocks VALUES (?,?,?)", [(line[0:6], float(line[7:14]), float(line[15:]))])
executemany()
与
?
占位符一起使用时,不需要事先将字符串转换为float。
executemany("INSERT INTO stocks VALUES (?,?,?)", [(line[0:6], line[7:14], line[15:])])
import time
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
elapsed = time.time()-self.start
print('Imported in {:.2f} seconds or {:.0f} per second'.format(elapsed, 1*1000*1000/elapsed))
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
c.execute('''DROP TABLE IF EXISTS stocks''')
c.execute('''CREATE TABLE IF NOT EXISTS stocks
(sym text, bid real, ask real)''')
c.execute('''PRAGMA synchronous = EXTRA''')
c.execute('''PRAGMA journal_mode = WAL''')
with Timer() as t:
with open('input.ssv', 'r') as infile:
lines = infile.read().splitlines()
for line in lines:
c.executemany("INSERT INTO stocks VALUES (?,?,?)", [(line[0:6], line[7:14], line[15:])])
conn.commit()
conn.close()
pass
时,测试结果显示每秒向普通文件插入4.32 m。当我插入到一个健壮的sqlite数据库时,它会下降到每秒0.564m的插入。在sqlite中,还有什么可以让它更快的呢?如果不是sqlite而是其他数据库系统呢?
最佳答案
如果python的解释器实际上是计时(第9节)与sqlite性能的一个重要因素,您可能会发现PyPy可以显著提高性能(python的sqlite3接口是用纯python实现的)。但是,如果您正在执行更多的字符串操作或有for循环,那么从CPython切换是值得的。
显然,如果SQLite之外的性能真的很重要,你可以尝试用更快的语言编写类似C/C++的语言。多线程可能有帮助,也可能没有帮助,这取决于数据库锁是如何实现的。
关于python - 如何在Python 3.6中提高SQLite插入性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52142645/
我正在开发一个 SQLite 数据库。数据库已经填满了,但我想重构它。这是我需要做的一个示例: 我目前有一张 table : CREATE TABLE Cars (ID INTEGER PRIMARY
我正在使用 Mono、SQLite、Dapper 和 Dapper 扩展。我可以从数据库中读取数据,但插入不起作用。我正在使用 sqlite 的 Mono 驱动程序。 错误并不能提供太多信息,至少对我
我有一个使用 SQLite 的 Windows Phone 8 应用程序。该应用程序具有许多数据库功能,并包含一个 sqlite 数据库文件,在运行该应用程序时,该文件将被复制到本地文件夹并进行访问。
为 sqlite 创建索引时有排序顺序。 https://sqlite.org/lang_createindex.html Each column name or expression can be
顾名思义,我怀疑如果有一些引用被删除的表会发生什么,例如表的某些字段的索引。 SQLite是否会自动处理?在执行drop命令之前,数据库所有者是否应注意任何实例? 最佳答案 我认为不需要家政服务。 S
我想知道是否有可能将从计数中获得的整数转换为REAL 类似于以下内容(尽管这不起作用) SELECT CAST (COUNT (ColumnA) AS Count) AS REAL) FROM Tab
我无法在SQLite数据库上执行一些更新。我正在Windows上使用SQLite 3 Shell。 我正在运行以下命令: update resovled_chrom_counts set genus
我知道SQLite中的触发器顺序是不确定的(您不能确定将首先执行哪个触发器),但是表约束和触发器之间的关系又如何呢? 我的意思是,假设我在一个列中有一个UNIQUE(或CHECK)约束,并且在该表上有
我的 CustomTags 表可能有一系列“临时”记录,其中 Tag_ID 为 0,并且 Tag_Number 将有一些五位数的值。 定期,我想清理我的 Sqlite 表以删除这些临时值。 例如,我可
我有A,B,C和D的记录。 我的SQL1 SELECT * FROM main_table order by main_table.date desc limit 2返回A和B。 我的SQL2 SEL
select round(836.0)返回836.0 我如何删除sqlite查询中的尾随零。 836.00应该是836 836.440应该是836.44 最佳答案 如果需要836.44,则需要十进制返
我正在研究RQDA中的文本,并且正在使用Firefox SQLite Manager访问数据库,以便可以更轻松地搜索文件。我创建并填充了虚拟表: CREATE VIRTUAL TABLE texts
我有这样的数据: table1 id | part | price 1 | ox900 | 100 2 | ox980 | 200 和 table2 id | part | price 1
我正在尝试将一些数据插入现有的SQLite表中。该表和数据库是使用相同的API创建的,但是由于某种原因,插入操作无效,并且从不给我任何错误消息。 我正在BlackBerry 9550模拟器上对此进行测
例如,我在名为SALARY的列中插入一个值。如果插入的值大于1000,我想将字符串HIGH插入到RANK列中,否则将插入LOW中。 我可以使用SQLite做到吗? 最佳答案 在插入之前使用触发器,然后
假设我有一个包含三列A,B,C的表t1,其中(A,B)包含唯一键(具有数十万行)。由于90%的查询将采用SELECT C FROM t1 WHERE A =?和B = ?,我想我要为A,B和C提供覆盖
在一个SQLite3数据库中,我有一个表“ projects”,其id字段由以下方式组成: [user id]_[user's project id] 例如,用户ID = 45,这是一些数据: 45_
我了解PRAGMA foreign_key和ON DELETE RESTRICT/NO ACTION的概念,但是我面临的是另一种情况。 我需要删除一个父行,但保持与之关联的子行。例如: CREATE
我的c#应用程序从Web服务1读取文件列表,并将完整的文件名插入table1,然后从第二个Web服务读取list并将它们插入到table2。 这些表具有相同的结构,如下所示: create table
我在以下情况下尝试将Record1的ID更新为Record2的ID: 两个表中的名称相同,并且 在Record2中权重更大。 记录1 | ID | Weight | Name | |----|----
我是一名优秀的程序员,十分优秀!