在the advice of fellow SO-ers之后,我将一个MS Access数据库(由于测试原因,一个小数据库)转换为SQLite。它有两个表,一个有5个条目,另一个有50个条目。
现在,我将在 QuLimma 和 QLexeis 下面的查询使用Access花了大约60ms(下面这个函数的总时间),但是使用SQLite需要大约830ms。 / p>
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
现在,在有人问“不是60毫秒还不够快?”之前,我想说我这样做是因为我有其他的Access文件和查询需要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, 'υψίπεδο', 'ΑΠ', '<αρχ. υψίπεδον, ουδ. του επιθ. υψίπεδος<ύψι "ψηλά" + πέδον');
总计:64k条目
表格词:
CREATE TABLE Words ( id INTEGER PRIMARY KEY, limma VARCHAR2(100), limmabody INTEGER DEFAULT 0, limmapro VARCHAR2(200));
INSERT INTO Words VALUES (1, 'υψι (αχώριστο μόριο)', 1, NULL);
INSERT INTO Words VALUES (2, 'ομο (αχώριστο μόριο)', 2, NULL);
INSERT INTO Words VALUES (3, 'διχο (αχώριστο μόριο)', 3, NULL);
总计:6k条目
第一个字段“id”是唯一的。
答案 0 :(得分:6)
您几乎不想在可以使用WHERE标准的地方使用HAVING。您正在评估所有可能的结果,然后在聚合后将其剔除。您主要想要根据聚合结果使用HAVING标准进行剔除。在这种情况下,通过在聚合之前将HAVING逻辑移动到WHERE条件,可以实现相同的目的。这应该会大大加快您的查询速度。
也没有必要使用GROUP BY逻辑,因为你没有返回任何聚合,只需使用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)
请记住,在插入每个附加索引时都会有成本。您必须权衡此成本与指数的好处。如果您的表包含静态数据,则没有任何危害。