优化SQLite很棘手.C应用程序的批量插入性能可以从每秒85次插入到每秒超过96,000次插入!
背景:我们使用SQLite作为桌面应用程序的一部分.我们有大量的配置数据存储在XML文件中,这些数据被解析并加载到SQLite数据库中,以便在初始化应用程序时进行进一步处理.SQLite非常适合这种情况,因为它速度快,不需要专门配置,数据库作为单个文件存储在磁盘上.
理由: 最初我对我所看到的表现感到失望.事实证明,SQLite的性能可能会有很大差异(对于批量插入和选择),具体取决于数据库的配置方式以及如何使用API.弄清楚所有选项和技术是什么并不是一件小事,所以我认为创建这个社区wiki条目以与Stack Overflow读者分享结果是谨慎的,以便为其他人节省相同调查的麻烦.
实验:我不是简单地谈论一般意义上的性能提示(即"使用事务!"),而是认为最好编写一些C代码并实际测量各种选项的影响.我们将从一些简单的数据开始:
我们来写一些代码吧!
代码:一个简单的C程序,它逐行读取文本文件,将字符串拆分为值,然后将数据插入SQLite数据库.在代码的这个"基线"版本中,创建了数据库,但我们实际上不会插入数据:
/*************************************************************
Baseline code to experiment with SQLite performance.
Input data is a 28 MB TAB-delimited text file of the
complete Toronto Transit System schedule/route info
from http://www.toronto.ca/open/datasets/ttc-routes/
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "sqlite3.h"
#define INPUTDATA "C:\\TTC_schedule_scheduleitem_10-27-2009.txt"
#define DATABASE "c:\\TTC_schedule_scheduleitem_10-27-2009.sqlite"
#define …Run Code Online (Sandbox Code Playgroud) 我在c ++中通过sqlite创建了一个数据库.
db已在内存中创建(使用文件名中的":memory:"参数),以便具有非常快速的行为.
数据库由以下行创建:
sqlite3* mem_database;
if((SQLITE_OK == sqlite3_open(":memory:", &mem_database)){
// The db has been correctly created and
// I can do some stuff with it.
}
sqlite3_close(mem_database);
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何将内存数据库写入磁盘?(当然是通过c/c ++).
我读了一些关于ATTACH和DETACH sqlite命令的内容,但我可以让它们只使用sqlite交互式shell(而不是c/c ++代码).
映入眼帘.
我编写了一个java应用程序,它偶尔会将事件从多个线程记录到SQLite数据库中.我注意到我可以通过同时生成少量事件来相对容易地触发SQLite的"数据库锁定"错误.这促使我编写了一个模拟最坏情况行为的测试程序,我很惊讶SQLite在这个用例中的表现有多糟糕.下面发布的代码只是将五条记录添加到数据库中,首先按顺序获取"控制"值.然后同时添加相同的五个记录.
import java.sql.*;
public class Main {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:test.db");
Statement stat = conn.createStatement();
stat.executeUpdate("drop table if exists people");
stat.executeUpdate("create table people (name, occupation)");
conn.close();
SqlTask tasks[] = {
new SqlTask("Gandhi", "politics"),
new SqlTask("Turing", "computers"),
new SqlTask("Picaso", "artist"),
new SqlTask("shakespeare", "writer"),
new SqlTask("tesla", "inventor"),
};
System.out.println("Sequential DB access:");
Thread threads[] = new Thread[tasks.length];
for(int i = 0; i < tasks.length; i++)
threads[i] = new Thread(tasks[i]);
for(int i = 0; i …Run Code Online (Sandbox Code Playgroud) 我正在编写一个应用程序,它必须经常记录信息,比如说,一秒钟两次.我希望将信息保存到sqlite数据库,但我不介意每十分钟提交一次磁盘更改.
使用文件数据库时执行查询需要很长时间,并使计算机滞后.
一个可选的解决方案是使用内存数据库(它适合,不用担心),并不时将其同步到磁盘,
可能吗?有没有更好的方法来实现它(你能告诉sqlite只在X查询后提交到磁盘吗?).
我可以解决这个用Qt的SQL包装器?
我正在尝试通过导入带有url的csv文件来创建一个sqlite数据库.该文件有大约600万字符串.这是我用过的命令
create table urltable (url text primary key);
.import csvfile urldatabase
Run Code Online (Sandbox Code Playgroud)
大约300万网址后,速度减慢了很多,我的硬盘不断旋转.我已经尝试将csv文件拆分为1/4块但我遇到了同样的问题.
我在stackoverflow上阅读了类似的帖子,尝试使用BEGIN...COMMIT块,PRAGMA synchronous=OFF但没有一个帮助.我能够创建数据库的唯一方法是从url中删除主键约束.但是,当我运行一个select命令来查找特定的url时,需要2-3秒,这对我的应用程序不起作用.在url上设置主键时,选择是即时的.请告诉我我做错了什么.
[编辑] 有助于提出的建议摘要:
仍然,使用主索引,数据库大小是我尝试导入的原始csv文件的两倍多.有什么方法可以减少吗?