Sqlite3读写速度跟什么有关?

西安鲲之鹏 发布于 2019/10/31 10:18
阅读 738
收藏 0

Linux基金会免费官方培训及考试申请即将截止,戳这里申请!>>>

用同一个Python脚本,测试读写sqlite3 1000次所用的时间,在四台机器上测试,发现结果差别巨大,搞不清到底跟什么指标有关系。请大神指点。

测试结果如下:

(1)个人工作PC,I5-7400,Win10,Python2。

测试结果如下图所示,总耗时178.8秒。

(2)公司40核服务器,Ubuntu,Python2。

测试结果如下图所示,总耗时3.8秒。

(3)徐州租用32核服务器,Ubuntu,Python2。

测试结果如下图所示,总耗时272.8秒。

(4)阿里云1核云主机,Ubuntu,Python2。

测试结果如下图所示,总耗时9.6秒。

 

测试结果总结如下表:

平台 CPU核数 耗时
个人工作PC 4核(I5-7400) 178.8秒
公司40核服务器 40核 3.88秒
徐州租用32核服务器 32核 372.8秒
阿里云1核云主机 1核 9.6秒

刚开始以为是跟CPU关系很大,但是测试结果看起来并非如此。请大神指点。

 

最后附上测试脚本:

# coding: utf-8
# speed_test.py

import zlib
import pickle
import time
import sqlite3
from datetime import datetime
            
            
def sqlite_test():
    """测试sqlite读写速度
    """
    # 待写入数据html
    with open('page.html') as f:
        html = f.read()
    print 'Original data size = {}'.format(len(html))    

    # 连接sqlite数据库,创建表
    start_time = time.time()
    conn = sqlite3.connect('test.db', timeout=10000, isolation_level=None, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
    conn.text_factory = lambda x: unicode(x, 'utf-8', 'replace') 
    sql = """
    CREATE TABLE IF NOT EXISTS cache (
        key TEXT NOT NULL PRIMARY KEY UNIQUE,
        value BLOB,
        updated timestamp DEFAULT (datetime('now', 'localtime'))
    );
    """
    conn.execute(sql)
    conn.execute("CREATE INDEX IF NOT EXISTS keys ON cache (key);")
    print 'Time used to create sqlite database: {} seconds.'.format(round(time.time() - start_time, 2))
    
    # 读写1000次测试
    test_times = 1000
    all_times_used = []
    start_time = time.time()
    for i in range(test_times):
        # 写入数据
        updated = datetime.now()
        key = 'cache-{}'.format(i)
        # 写数据
        conn.execute("INSERT OR REPLACE INTO cache (key, value, updated) VALUES(?, ?, ?);", (
            key, html, updated)
        ) 
        # 读取数据
        row = conn.execute("SELECT value, updated FROM cache WHERE key=?;", (key,)).fetchone()
        i += 1
        if i % 100 == 0:
            # 每100次,输出一次用时
            times_used = round(time.time() - start_time, 2)
            all_times_used.append(times_used)
            print '[{}] {}'.format(times_used, i)
            start_time = time.time()
    print 'Total used {} seconds, avg time used for per write-read op: {} seconds.'.format(sum(all_times_used), round(sum(all_times_used)/float(test_times), 4))


if __name__ == '__main__':
    sqlite_test()

再补充一下做这个测试的背景:公司一爬虫脚本在不同机器上运行速度差别很大,一路追踪最后发现是跟读写缓存数据库有关,缓存数据库用的sqlite,于是有了该测试。

加载中
0
LibreSoft
LibreSoft

开启wal模式呢?

0
gammey
gammey

估计和磁盘IO有关,换个SSD应该会快不少。

0
西安鲲之鹏
西安鲲之鹏

引用来自“gammey”的评论

估计和磁盘IO有关,换个SSD应该会快不少。

我一开始怀疑是和IO有关,但是我在表现最差的服务器和表现最好的服务器上,对比测了磁盘(测试脚本运行所在磁盘)性能:

表现最差的机器(sqlite测试耗时最长的徐州32核心服务器):236 MB/s

kzp@zhx-tickets-spider-server4:~/temp$ sudo dd if=/dev/zero of=/home/linshi.a bs=1024000000 count=2
2+0 records in
2+0 records out
2048000000 bytes (2.0 GB) copied, 8.67662 s, 236 MB/s

 

表现最好的机器(sqlite测试耗时最短的公司40核心服务器):208 MB/s

qi@kunzhipeng-server3:/data/sdg/temp$ sudo dd if=/dev/zero of=/home/linshi.a bs=1024000000 count=2
2+0 records in
2+0 records out
2048000000 bytes (2.0 GB, 1.9 GiB) copied, 9.86872 s, 208 MB/s

 

表现最好机器的磁盘速度竟然还没表现最差的快!

0
头号大宝贝
头号大宝贝

和线程无关,sqlite是单线程写操作。

关闭wal模式,默认是开。打开只是加一个类似log的缓存,定时入库。

关闭自动提交,默认是开。建议代码操作使用批量增删改,而不是一句一句执行。

字段尽可能的不使用TEXT。

 

机械磁盘瓶颈2G,SSD瓶颈12G。亲测过。

返回顶部
顶部