提高sqlite 的运行性能(转载)
原文地址:
https://blog.devart.com/increasing-sqlite-performance.html
One the major issues a developer encounters when using the SQLite DBMS in his applications is its performance issue.
Perhaps, a classic case everyone gets into when using SQLite for the first time is very slow execution of multiple INSERT/UPDATE/DELETE operations. Indeed, sequential executions of not even thousands, but hundreds of INSERTs into a table may take too long.The origin of the issue lies in the specificity of using transactions in SQLite. SQLite starts a transaction automatically every time before any DML statement execution and commits it after execution. Accordingly, when executing multiple consequent statements, a new transaction will be started and committed for each statement.
The solution of this problem is quite simple — the block of DML statements may be enclosed into BEGIN … END operators block ( https://www.sqlite.org/lang_transaction.html). In this case, each DML statement won’t be executed in a separate transaction, but a single transaction will be started before the whole block execution and committed after all modifications.
Such an approach increases SQLite data modification performance by times. See more details about it in the SQLite documentation (https://www.sqlite.org/faq.html#q19).
However, this approach is not the only way to increase performance in SQLite. Parameters of the DBMS may also be configured using so-called PRAGMA (https://www.sqlite.org/pragma.html). The fact is that SQLite parameters are oriented not to high performance by default, but to maximum data safety and integrity. Modification of these parameters may increase performance, however, note, that the data corruption risks increase too.
Let’s analyze the impact to inserts performance by different PRAGMAs using LiteDAC.
We will use a test table SPEED_TEST in our project:
ID INTEGER,
F_INTEGER INTEGER,
F_FLOAT FLOAT,
F_STRING VARCHAR(250),
F_DATE DATETIME,
CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)
)
|
1
2
3
4
5
6
7
8
|
CREATE TABLE SPEED_TEST (
ID INTEGER,
F_INTEGER INTEGER,
F_FLOAT FLOAT,
F_STRING VARCHAR(250),
F_DATE DATETIME,
CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)
)
|
In each test, we will delete the database and re-create it, and then insert 10,000 records to the SPEED_TEST table as follows:
LiteQuery: TLiteQuery;
i: Integer;
ParamID, ParamF_INTEGER, ParamF_FLOAT, ParamF_STRING, ParamF_DATE: TDAParam;
begin
...
LiteQuery.SQL.Text := 'INSERT INTO SPEED_TEST VALUES (:ID, :F_INTEGER, :F_FLOAT, :F_STRING, :F_DATE)'; ParamID := LiteQuery.Params.ParamByName('ID');
ParamID.DataType := ftInteger;
ParamF_INTEGER := LiteQuery.Params.ParamByName('F_INTEGER');
ParamF_INTEGER.DataType := ftInteger;
ParamF_FLOAT := LiteQuery.Params.ParamByName('F_FLOAT');
ParamF_FLOAT.DataType := ftFloat;
ParamF_STRING := LiteQuery.Params.ParamByName('F_STRING');
ParamF_STRING.DataType := ftWideString;
ParamF_DATE := LiteQuery.Params.ParamByName('F_DATE');
ParamF_DATE.DataType := ftDateTime;
for i := 0 to 10000 - 1 do begin
ParamID.AsInteger := i + 1;
ParamF_INTEGER.AsInteger := i + 5000 + 1;
ParamF_FLOAT.AsFloat := (i + 1) / 15;
ParamF_STRING.AsString := 'Values ' + IntToStr(i + 1);
ParamF_DATE.AsDateTime := Now;
LiteQuery.Execute;
end;
...
end;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
var
LiteQuery: TLiteQuery;
i: Integer;
ParamID, ParamF_INTEGER, ParamF_FLOAT, ParamF_STRING, ParamF_DATE: TDAParam;
begin
...
LiteQuery.SQL.Text := 'INSERT INTO SPEED_TEST VALUES (:ID, :F_INTEGER, :F_FLOAT, :F_STRING, :F_DATE)'; ParamID := LiteQuery.Params.ParamByName('ID');
ParamID.DataType := ftInteger;
ParamF_INTEGER := LiteQuery.Params.ParamByName('F_INTEGER');
ParamF_INTEGER.DataType := ftInteger;
ParamF_FLOAT := LiteQuery.Params.ParamByName('F_FLOAT');
ParamF_FLOAT.DataType := ftFloat;
ParamF_STRING := LiteQuery.Params.ParamByName('F_STRING');
ParamF_STRING.DataType := ftWideString;
ParamF_DATE := LiteQuery.Params.ParamByName('F_DATE');
ParamF_DATE.DataType := ftDateTime;
for i := 0 to 10000 - 1 do begin
ParamID.AsInteger := i + 1;
ParamF_INTEGER.AsInteger := i + 5000 + 1;
ParamF_FLOAT.AsFloat := (i + 1) / 15;
ParamF_STRING.AsString := 'Values ' + IntToStr(i + 1);
ParamF_DATE.AsDateTime := Now;
LiteQuery.Execute;
end;
...
end;
|
We’ll run the test project on 2 platforms: Microsoft Windows 7 x86 and MacOS X 10.9 Mavericks.
PRAGMA TEMP_STORE
This parameter allows to specify location of temporary objects in the database: tables, indexes, triggers, views, etc. PRAGMA TEMP_STORE accepts 3 values:
- 0 | DEFAULT — the default value, when location of temporary objects storage is defined by the option, which is set during SQLite compilation;
- 1 | FILE — temporary objects are stored in a file (its location depends on the used OS);
- 2 | MEMORY — temporary objects are stored in memory.
When the TEMP_STORE parameter is changed, all the temporary tables, indexes, triggers, views are deleted.
Time: sec
| Microsoft Windows 7 x86 | ||
|---|---|---|
| DEFAULT | FILE | MEMORY |
| 235 | 225 | 215 |
| MacOS X 10.9 Mavericks | ||
|---|---|---|
| DEFAULT | FILE | MEMORY |
| 34 | 33 | 32 |
According to the retrieved results, making RAM a storage for temporary DB objects increases performance a little.
PRAGMA JOURNAL_MODE
The parameter sets the database log working mode (rollback journal file used on transaction processing).
PRAGMA JOURNAL_MODE accepts the following values:
- DELETE (the default value) — in this mode the log file is deleted after transaction is committed.
- TRUNCATE — after transaction is committed, the log file is truncated to 0 size. This works faster than log deleting on a number of platforms, since the catalog containing the log file is not modified at this.
- PERSIST — instead of deleting and truncating, the log file header is filled in with zeros. In this case, the log file size doesn’t change and it can require quite much space. However, such an operation may be executed faster than DELETE or TRUNCATE.
- MEMORY — the rollback journal is kept in RAM and doesn’t use the disk subsystem. Such mode provides more significant performance increase when working with log. However, in case of any failures within a transaction, data in the DB will be corrupted with high probability due to a lack of saved data copy on the disk.
- OFF — not using log. In this mode, transaction rollback is impossible. In case of a crash, the database will be likely corrupted.
Time: sec
| Microsoft Windows 7 x86 | ||||
|---|---|---|---|---|
| DELETE | TRUNCATE | PERSIST | MEMORY | OFF |
| 235 | 210 | 220 | 65 | 63 |
| MacOS X 10.9 Mavericks | ||||
|---|---|---|---|---|
| DELETE | TRUNCATE | PERSIST | MEMORY | OFF |
| 34 | 4 | 3 | 2 | 1 |
Changing this parameter significantly increases performance when inserting data on both platforms. Note, that at using MEMORY or OFF values, the risk of data loss is maximal too.
PRAGMA SYNCHRONOUS
Defines the mode of rollback journal synchronization with the data.
- 2 | FULL — the default value. SQLite pauses working in critical cases, in order to guarantee 100% data integrity when saving to the database file — even on system crash or power failure. This synchronization mode is absolutely safe, but the most slow.
- 1 | NORMAL — SQLite will pause in critical cases as well, but less often in the FULL mode. At this value, there is a (quite small) data corruption possibility. The NORMAL mode is a compromise between reliability and performance.
- 0 | OFF — database synchronization is not used. I.e., SQLite takes no breaks when transmitting data to the operating system. Such mode can substantially increase performance. The database will meet the integrity conditions after the SQLite crash, however, data will be corrupted in case of system crash or power off.
Time: sec
| Microsoft Windows 7 x86 | ||
|---|---|---|
| FULL | NORMAL | OFF |
| 235 | 175 | 43 |
| MacOS X 10.9 Mavericks | ||
|---|---|---|
| FULL | NORMAL | OFF |
| 34 | 32 | 32 |
The test demonstrated significant performance increase on Windows. It is highly recommended to speed up performance this way only with assurance of the operating system stability and power quality.
PRAGMA LOCKING_MODE
Defines the locking mode.
- NORMAL — the default value. The database file is locked at the moment of record reading or writing. After the operation completes, the lock is released.
- EXCLUSIVE — the database file is used in exclusive mode. The number of system calls to implement file operations decreases in this case, which may increase database performance.
Time: sec
| Microsoft Windows 7 x86 | |
|---|---|
| NORMAL | EXCLUSIVE |
| 235 | 155 |
| MacOS X 10.9 Mavericks | |
|---|---|
| NORMAL | EXCLUSIVE |
| 34 | 3 |
The most secure approach to increase performance. Though, EXCLUSIVE MODE allows the database to serve only one connection.
PRAGMA CACHE_SIZE
Defines the number of pages from the database file for storing in RAM, i.e., the cache size. Increasing this parameter may increase performance of the database on high load, since the greater its value is, the more modifications a session can perform before retrieving exclusive lock.
Time: sec
| Microsoft Windows 7 x86 | ||||||
|---|---|---|---|---|---|---|
| 0 | 500 | 1000 | 2000 | 4000 | 8000 | 10000 |
| 222 | 185 | 230 | 230 | 230 | 230 | 250 |
| MacOS X 10.9 Mavericks | ||||||
|---|---|---|---|---|---|---|
| 0 | 500 | 1000 | 2000 | 4000 | 8000 | 10000 |
| – | 34 | 34 | 34 | 34 | 34 | 34 |
Performance increase is observed only on Windows. Changing this parameter is almost secure, yet the performance growth is minor.
PRAGMA PAGE_SIZE
Defines the database page size.
The page size is set by default depending on some computer and OS specifications. They include disk sector size and the used encoding. SQLite supports page size range from 512 to 65536 bytes.
Time: sec
| Windows 7 x86 | |||||||
|---|---|---|---|---|---|---|---|
| 512 | 1024 | 2048 | 4096 | 8192 | 16384 | 32768 | 65535 |
| 240 | 235 | 227 | 225 | 255 | 295 | 450 | 295 |
| MacOS X 10.9 Mavericks | |||||||
|---|---|---|---|---|---|---|---|
| 512 | 1024 | 2048 | 4096 | 8192 | 16384 | 32768 | 65535 |
| 34 | 34 | 33 | 33 | 34 | 40 | 50 | 65 |
Like the previous parameter, PRAGMA PAGE_SIZE is almost safe with respect to risk of data corruption, however, tuning of this parameter doesn’t lead to significant performance increase and requires search for values depending on the used sector size.
Summary
- There are ways to increase SQLite data insert performance in addition to using transactions.
- Usage of PRAGMA may significantly increase performance of SQLite.
- SQLite default settings don’t provide optimal performance, yet guarantee absolute data integrity and safety.
- Changing SQLite parameter values in favor of performance increases the risk of data corruption.
- Values of some parameters (PRAGMA PAGE_SIZE, PRAGMA CACHE_SIZE) should be found depending on specifications of the used environment.
提高sqlite 的运行性能(转载)的更多相关文章
- 通过分区(Partitioning)提高Spark的运行性能
在Sortable公司,很多数据处理的工作都是使用Spark完成的.在使用Spark的过程中他们发现了一个能够提高Sparkjob性能的一个技巧,也就是修改数据的分区数,本文将举个例子并详细地介绍如何 ...
- 修改Tomcat Connector运行模式,优化Tomcat运行性能
Tomcat是一个小型的轻量级应用服务器,也是JavaEE开发人员最常用的服务器之一.不过,许多开发人员不知道的是,Tomcat Connector(Tomcat连接器)有bio.nio.apr三种运 ...
- 修改 Tomcat Connector运行模式 优化Tomcat运行性能
omcat是一个小型的轻量级应用服务器,也是JavaEE开发人员最常用的服务器之一.不过,许多开发人员不知道的是,Tomcat Connector(Tomcat连接器)有bio.nio.apr三种运行 ...
- 利用 squid 反向代理提高网站性能(转载)
本文在介绍 squid 反向代理的工作原理的基础上,指出反向代理技术在提高网站访问速度,增强网站可用性.安全性方面有很好的用途.作者在具体的实验环境下,利用 DNS 轮询和 Squid 反向代理技术, ...
- 【转载】总结使用Unity3D优化游戏运行性能的经验
流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏<Shadow Blade>已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标. 以下是我们在紧凑的优化过程中 ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html
JVM系类的文章全部转载自:http://www.cnblogs.com/kubixuesheng/p/5199200.html 特别在此声明.那位博主写的真的很好 ,感谢!! 俗话说,自己写的代码, ...
- 提高 Linux 上 socket 性能
http://www.cnblogs.com/luxf/archive/2010/06/13/1757662.html 基于Linux的Socket网络编程的性能优化 1 引言 随着In ...
- 通过硬件层提高Android动画的性能
曾有许多人问我为什么在他们开发的应用中,动画的性能表现都很差.对于这类问题,我往往会问他们:你们有尝试过在硬件层解决动画的性能问题么? 我们都知道,在播放动画的过程中View在每一帧动画的显示时重绘自 ...
- 修改Linux内核参数提高Nginx服务器并发性能
当linux下Nginx达到并发数很高,TCP TIME_WAIT套接字数量经常达到两.三万,这样服务器很容易被拖死.事实上,我们可以简单的通过修改Linux内核参数,可以减少Nginx服务器 的TI ...
随机推荐
- POJ1167 The Buses
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6234 Accepted: 1698 Description A man ...
- 洛谷 P 1133 教主的花园
题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树 ...
- 計算 battery impedence
Origin 一顆電池被拉載後,會產生電流及電壓如下圖, 如何計算其電池內阻呢 其公式為 R = |delta(V) / delta(I)| 公式推導如下: V1 = 10 - I1R --- 左圖 ...
- poj 1970(搜索)
The Game Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6247 Accepted: 1601 Descript ...
- AC日记——花店橱窗布置 codevs 1028
题目描述 Description 假设以最美观的方式布置花店的橱窗,有F束花,V个花瓶,我们用美学值(一个整数)表示每束花放入每个花瓶所产生的美学效果.为了取得最佳的美学效果,必须使花的摆放取得最大的 ...
- Python的格式化输出,基本运算符,编码
一. 格式化输出现在有以下需求,让用户输入name, age, job,hobby 然后输出如下所示: -----------info of Alex Li----------- Name : Ale ...
- 精读《Function Component 入门》
1. 引言 如果你在使用 React 16,可以尝试 Function Component 风格,享受更大的灵活性.但在尝试之前,最好先阅读本文,对 Function Component 的思维模式有 ...
- CMDB与自动化运维,一切尽在掌握中?
生产力跟不上生产的速度时,就会出现很多问题,如何针对问题进行处理,制定什么样的计划,如何解决就是需要思考的难点? T运维的分类 IT运维,指的是对已经搭建好的网络,软件,硬件进行维护.运维领域也是细分 ...
- 51Nod 约数之和
1220 约数之和 题目来源: Project Euler 基准时间限制:3 秒 ...
- Cookie安全与CSRF和XSS攻击知识点收集
个人简单理解: 1.XSS最简单的理解就是可以在表单提交的内容上嵌入JS执行代码,然后页面渲染的时候没有过滤时会自动执行这个脚本. 2.CSRF可以理解为当你登录了京东,浏览器上保存了你登录的Cook ...