与MS Access相比,SQLite速度非常慢

与MS Access相比,SQLite速度非常慢,sql,database,sqlite,ms-access,Sql,Database,Sqlite,Ms Access,接下来,我将一个MS Access数据库(出于测试原因,一个小数据库)转换为SQLite。它有两个表,一个有5k个条目,另一个有50k个条目 现在,我将在下面介绍的查询qulima和qlexis使用Access大约需要60毫秒(下面函数的总时间),而使用SQLite则需要830毫秒 Dim i As Integer Dim ms As Integer ResultPin(0) = "" ResultPin(1) = "" ResultPin(2) = "" ResultPin(3) = "" R

接下来,我将一个MS Access数据库(出于测试原因,一个小数据库)转换为SQLite。它有两个表,一个有5k个条目,另一个有50k个条目

现在,我将在下面介绍的查询qulimaqlexis使用Access大约需要60毫秒(下面函数的总时间),而使用SQLite则需要830毫秒

Dim i As Integer
Dim ms As Integer
ResultPin(0) = ""
ResultPin(1) = ""
ResultPin(2) = ""
ResultPin(3) = ""
ResultPin(4) = ""
i = 0
Multichoice = 0
ms = 0

Dim rsTblEntries As ADODB.Recordset
Set rsTblEntries = New ADODB.Recordset

Dim QuLimma As String, QLexeis As String
QuLimma = "SELECT Words.limma, Words.limmabody, Words.limmapro " & _
        "FROM Words " & _
        "GROUP BY Words.limma, Words.limmabody, Words.limmapro " & _
        "HAVING (((Words.limma)='" & StrLexeis & "'));"
QLexeis = "SELECT Limma.limmalexeis, Words.limma, Limma.limmabody, Words.limmapro, Limma.limmaexp " & _
        "FROM Limma INNER JOIN Words ON Limma.limmabody = Words.limmabody " & _
        "GROUP BY Limma.limmalexeis, Words.limma, Limma.limmabody, Words.limmapro, Limma.limmaexp " & _
        "HAVING (((Limma.limmalexeis)='" & StrLexeis & "'));"

rsTblEntries.Open QuLimma, CnDataParSQLite ', adOpenStatic, adLockOptimistic
If rsTblEntries.EOF = True Then
    rsTblEntries.Close
    rsTblEntries.Open QLexeis, CnDataParSQLite ', adOpenStatic, adLockOptimistic
    If rsTblEntries.EOF = True Then
        SearchQParagSQLite = False
    Else
        SearchQParagSQLite = True
        Do While rsTblEntries.EOF = False
            ms = ms + 1
            rsTblEntries.MoveNext
        Loop
        rsTblEntries.MoveFirst
        If ms > 1 Then
            Do While rsTblEntries.EOF = False
                ResultTemp(0, i) = rsTblEntries.Fields("limma").Value & "" 'rsWordPar!limma
                ResultTemp(1, i) = rsTblEntries.Fields("limmalexeis").Value & "" 'rsWordPar!limmalexeis
                ResultTemp(2, i) = rsTblEntries.Fields("limmabody").Value 'rsWordPar!limmabody
                If IsNull(rsTblEntries.Fields("limmapro").Value) = False Then ResultTemp(3, i) = rsTblEntries.Fields("limmapro").Value 'rsWordPar!limmapro
                rsTblEntries.MoveNext
                i = i + 1
                Multichoice = 1
            Loop
        Else
            Do While rsTblEntries.EOF = False
                ResultPin(0) = rsTblEntries.Fields("limma").Value & "" 'rsWordPar!limma
                ResultPin(1) = rsTblEntries.Fields("limmalexeis").Value & "" 'rsWordPar!limmalexeis
                ResultPin(2) = rsTblEntries.Fields("limmabody").Value 'rsWordPar!limmabody
                If IsNull(rsTblEntries.Fields("limmapro").Value) = False Then ResultPin(3) = rsTblEntries.Fields("limmapro").Value 'rsWordPar!limmapro
                rsTblEntries.MoveNext
                Multichoice = 0
            Loop
        End If
    End If
Else
     SearchQParagSQLite = True
     rsTblEntries.MoveFirst
     Do While rsTblEntries.EOF = False
        ResultPin(0) = rsTblEntries.Fields("limma").Value & "" 'rsWordPar!limma
        ResultPin(1) = "#"
        ResultPin(2) = rsTblEntries.Fields("limmabody").Value 'rsWordPar!limmabody
        If IsNull(rsTblEntries.Fields("limmapro").Value) = False Then ResultPin(3) = rsTblEntries.Fields("limmapro").Value 'rsWordPar!limmapro
        rsTblEntries.MoveNext
        i = i + 1
     Loop
End If
i = 0

rsTblEntries.Close
Set rsTblEntries = Nothing
使用连接字符串:

CnDataParSQLite.ConnectionString = "DRIVER=SQLite3 ODBC Driver;" & _
                          "Database=" & strDataPath & "u.sl3;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
CnDataParSQLite.Open
现在,在有人问“60ms不够快吗?”之前,我想说,我这样做是因为我有其他需要3-4秒的访问文件和查询,我想降低它们,所以是的,我希望在这一次中从60ms降低到30或更少

我是否有一个错误的配置,或者仅仅是SQLite没有更快?我已经检查过了,都返回了正确的结果,没有奇怪的循环问题

编辑:大部分时间用于第二次查询

编辑2:(从db.sql复制/粘贴)

表Limma:

CREATE TABLE Limma ( id INTEGER PRIMARY KEY, limmabody INTEGER DEFAULT 0, limmalexeis VARCHAR2(100), limmastat VARCHAR2(50), limmaexp VARCHAR2(250));
INSERT INTO Limma VALUES (1, 1, 'υψικάμινος', 'ΣΠ', NULL);
INSERT INTO Limma VALUES (2, 1, 'υψίκορμος', 'ΣΠ', NULL);
INSERT INTO Limma VALUES (3, 1, 'υψίπεδο', 'ΑΠ', '<αρχ. υψίπεδον, ουδ. του επιθ. υψίπεδος<ύψι "ψηλά" + πέδον');
总数:6千份


第一个字段“id”是唯一的。

您几乎不想使用have-where-You-can-use-where条件。您正在评估所有可能的结果,然后在聚合后将其剔除。您主要希望使用HAVING条件,根据聚合结果进行筛选。在本例中,通过将HAVING逻辑移动到聚合之前的WHERE条件,可以实现同样的效果。这将大大加快您的查询速度

也不需要使用GROUPBY逻辑,因为您不返回任何聚合,只需使用DISTINCT

我会这样写:

QuLimma = "SELECT DISTINCT Words.limma, Words.limmabody, Words.limmapro " & _
    "FROM Words " & _
    "WHERE Words.limma ='" & StrLexeis & "';"
QLexeis = "SELECT DISTINCT Limma.limmalexeis, Words.limma, Limma.limmabody, Words.limmapro, Limma.limmaexp " & _
    "FROM Limma INNER JOIN Words ON Limma.limmabody = Words.limmabody " & _
    "WHERE Limma.limmalexeis ='" & StrLexeis & "';"
对于具有表架构的这两个查询,这些索引应优化查询:

CREATE NONCLUSTERED INDEX ix_words_1 ON Words (Limma) INCLUDE (Limmabody, Limmapro)
CREATE NONCLUSTERED INDEX ix_words_2 ON Words (Limmabody) INCLUDE (Limma, Limmapro)
CREATE NONCLUSTERED INDEX ix_limma_1 ON Limma (Limmabody, Limmalexeis) INCLUDE (Limmaexp)

请记住,插入时,您拥有的每个附加索引都有一个成本。你必须权衡这个成本和指数的好处。如果您的表包含静态数据,则不会有任何损害。

谢谢您的回复。也许我还缺少一个表索引?我刚刚将数据库从access转换为sqlite,但我不知道是否应该为其编制索引以及如何编制索引。如果没有索引,您肯定需要在表上添加索引。我无法从你的专栏中确切地看出它们的用途。您能提供完整的表定义并描述每列是什么吗?我自己或其他人应该能够为您提供一个复制粘贴“createindex”语句,其中包含这些信息。我用表格定义和解释更新了我的初始帖子。非常感谢!每个表上的“id”列的意义是什么,您是否用它进行过查询或筛选?它只是一个自动编号,有时会被查询(不是在这两个特定的查询上)。您说您去了Sqlite,但您的表定义看起来像Oracle。我认为Sqlite没有“Varchar2”数据类型。请运行“Select value from SYS.NLS_DATABASE_PARAMETERS,其中PARAMETER='NLS_CHARACTERSET'”,然后发布输出。如果数据库未设置为使用unicode字符集,则可能需要更改表定义并重新开始。@LoveLearn,摘录自转换过程中的中间.sql文件(ms access->.sql->sqlite3您肯定应该做一些研究,以确保您的列正确存储unicode值。如果它们正确,则一切正常,但如果它们不正确,则需要更新您的数据类型。这可能很好,但如果它们不正确,则可能会有点灾难性。如果您能够在access中加快查询速度,w你还对切换到SQLite感兴趣吗?这让人困惑。
CREATE NONCLUSTERED INDEX ix_words_1 ON Words (Limma) INCLUDE (Limmabody, Limmapro)
CREATE NONCLUSTERED INDEX ix_words_2 ON Words (Limmabody) INCLUDE (Limma, Limmapro)
CREATE NONCLUSTERED INDEX ix_limma_1 ON Limma (Limmabody, Limmalexeis) INCLUDE (Limmaexp)