优化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) 我有一组数据要一次插入,比如4行.
我的表有三列:Person,Id和Office.
INSERT INTO MyTable VALUES ("John", 123, "Lloyds Office");
INSERT INTO MyTable VALUES ("Jane", 124, "Lloyds Office");
INSERT INTO MyTable VALUES ("Billy", 125, "London Office");
INSERT INTO MyTable VALUES ("Miranda", 126, "Bristol Office");
Run Code Online (Sandbox Code Playgroud)
我可以Person在一个单独的所有4行Id?
我想将我的iPhone应用程序迁移到新的数据库版本.由于我没有保存某些版本,我需要检查是否存在某些列名.
此Stackoverflow条目建议执行select
SELECT sql FROM sqlite_master
WHERE tbl_name = 'table_name' AND type = 'table'
Run Code Online (Sandbox Code Playgroud)
并解析结果.
这是常见的方式吗?备择方案?
我试图在SQLite(最新版本)表中插入多行但引发错误
从这里得到了这个想法,这是我的SQL查询:
INSERT INTO "Track"
SELECT "Leonard Collections" AS "Album",
"Instrumental" AS "Artist",
"00:02:59.3800000" AS "Duration",
"1/1/0001 12:00:00 AM" AS "ReleasedDate",
"If You Love Me" AS "Title",
"False" AS "IsPlayableOnLocal"
UNION
SELECT "Leonard Collections",
"Instrumental",
"00:02:56.6930000",
"1/1/0001 12:00:00 AM",
"Espoir",
"False",
UNION
SELECT "Leonard Collections",
"Instrumental",
"00:03:51.6770000",
"1/1/0001 12:00:00 AM",
"Don't Cry For My Argentina",
"False"
Run Code Online (Sandbox Code Playgroud)
但它会抛出
SQL logic error or missing database
near "UNION": syntax error
Run Code Online (Sandbox Code Playgroud)
这是我的表结构
CREATE TABLE Track
(
ID INTEGER PRIMARY KEY AUTOINCREMENT NOT …Run Code Online (Sandbox Code Playgroud) 给出一张表:
CREATE TABLE Foo(
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT
);
Run Code Online (Sandbox Code Playgroud)
如何使用以下命令返回同时插入的多行的ID:
INSERT INTO Foo (Name) VALUES
('A'),
('B'),
('C');
Run Code Online (Sandbox Code Playgroud)
我知道last_insert_rowid()但我没有找到任何将它用于多行的示例.
在这个SQL Server示例中可以看到我想要实现的目标:
DECLARE @InsertedRows AS TABLE (Id BIGINT);
INSERT INTO [Foo] (Name) OUTPUT Inserted.Id INTO @InsertedRows VALUES
('A'),
('B'),
('C');
SELECT Id FROM @InsertedRows;
Run Code Online (Sandbox Code Playgroud)
很感谢任何形式的帮助.
使用SQLAlchemy Core(而不是ORM),我试图使用值中的子查询来插入多行.对于MySQL,实际的SQL看起来像这样:
INSERT INTO widgets (name, type) VALUES
('Melon', (SELECT type FROM widgetTypes WHERE type='Squidgy')),
('Durian', (SELECT type FROM widgetTypes WHERE type='Spiky'))
Run Code Online (Sandbox Code Playgroud)
但是我values()在一个insert()只允许我一次插入一个子句的子句上使用该方法时似乎只能使用子查询.我想用他们全部传递给在一次插入多个值Connection的execute()方法的绑定参数列表,但是这似乎并没有得到支持.
有可能在一次通话中做我想做的事execute()吗?
这是一个独立的演示.请注意,这使用sqlite引擎,它不像MySQL那样支持多次插入,但SQLAlchemy代码仍然以与真实MySQL应用程序相同的方式失败.
from sqlalchemy import *
if __name__ == "__main__":
# Construct database
metadata = MetaData()
widgetTypes = Table('widgetTypes', metadata,
Column('id', INTEGER(), primary_key=True),
Column('type', VARCHAR(), nullable=False),
)
widgets = Table('widgets', metadata,
Column('id', INTEGER(), primary_key=True),
Column('name', VARCHAR(), nullable=False),
Column('type', INTEGER(), nullable=False),
ForeignKeyConstraint(['type'], ['widgetTypes.id']),
)
engine = …Run Code Online (Sandbox Code Playgroud) 在MySQL我会用
INSERT INTO `mytable` (`col1`, `col2`) VALUES
(1, 'aaa'),
(2, 'bbb');
Run Code Online (Sandbox Code Playgroud)
但这会导致SQLite出错.SQLite的正确语法是什么?
我有insert以下格式从网络下载的800条语句:
insert into mytable(col1,..,coln) values(val1,..valn);insert into mytable col...
我听说过交易,ContentValues和使用,union但我无法弄清楚哪一种更适合这种情况.
截断后在sqlite数据库中插入它们的最佳方法是什么mytable?
我使用以下方法为android项目将单行插入数据库.
myDB.execSQL("INSERT INTO "
+ Buss
+ " (BussName, RouteName)"
+ " VALUES ('buss1', 'buss2');");
Run Code Online (Sandbox Code Playgroud)
它工作正常.我看到这个链接在sqlite数据库中插入多行.我在我的android项目中尝试这种方法(插入多行),但它不起作用.
myDB.execSQL("INSERT INTO "
+ Buss
+ " (BussName, RouteName)"
+ " VALUES ('buss1', 'buss2'),('buss1', 'buss2'),('buss1', 'buss2');");
Run Code Online (Sandbox Code Playgroud)
怎么做?
为了根据 ID 列表(即不同的主键)查询 sqlite 表,我使用了以下语句(基于Chinook 数据库的示例 ):
SELECT * FROM Customer WHERE CustomerId IN (1,2,3,8,20,35)
Run Code Online (Sandbox Code Playgroud)
但是,我的实际 ID 列表可能会变得相当大(> 1000)。因此,我想知道这种使用IN语句的方法是否最有效,或者是否有更好/优化的方法来基于主键列表查询 sqlite 表。
sqlite ×8
sql ×4
android ×2
insert ×2
performance ×2
bulkinsert ×1
c ×1
iphone ×1
optimization ×1
primary-key ×1
python ×1
select ×1
sql-server ×1
sqlalchemy ×1
t-sql ×1