使用System.Data.SQLite(C#)进行SQLite查询比使用SQLiteStudio慢得多

时间:2019-03-17 21:04:21

标签: sqlite

我有一个查询,该查询在同一张表上运行多个联接。它与SessionID连接,该键不代表表中的列,而是通过子字符串操作生成为new column的键(请参见下面的查询代码)。

因此,我无法在SessionID上主动创建索引,因为该列在相关表Logs中不存在。

但是,当我在SQLiteStudio(v3.1.1)中运行查询时,查询运行得非常快。当我在SQLiteStudio中运行解释查询计划时,确实看到以下输出:

1   0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)

2   0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)

0   0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)

0   1   1   SEARCH SUBQUERY 1 AS b USING AUTOMATIC COVERING INDEX (SessionID=?)

0   2   2   SEARCH SUBQUERY 2 AS c USING AUTOMATIC COVERING INDEX (SessionID=?)

我们可以看到,SQLite正在使用自动覆盖索引SessionID。

当通过System.Data.SQLite从我的C#对相同的数据库运行相同的查询时,查询速度显着降低(大约50倍)。

当我在C#中运行解释查询计划时,确实看到了以下输出:

7   0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
14  0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
48  0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)

请注意,没有使用自动覆盖索引。

我尝试使用Analyze,并且还为SQLite连接显式设置了automatic_index = true,但这并没有影响查询计划。

SQLite查询为:

select a.username, a.PSMID, a.PSMHost, a.AccountName, A.TargetHost, a.TargetUser, 
  Case When info2 Not like '%DataBase=%' Then '' Else substr(info2, instr(info2, 'DataBase=') +9, (instr(info2, ';Dst') +- instr(info2, 'DataBase=') - 9)) End as TargetDataBase, a.ConnectionComponent, a.StartTime, 
  Case when c.time is not null then c.time else b.EndTime end as EndTime, 
  Case when c.SessionDuration is not null then c.SessionDuration else b.SessionDuration end as SessionDuration, 
  Case When c.RequestReason not like '%PSMSR169E%' and c.RequestReason != '' then 'Yes' else 'No' End as ErrorOccurred, 
  Case When c.RequestReason like '%PSMSR169E%' Then 'Yes' Else 'No' End as DurationElapsed, c.RequestReason As Message  
from (SELECT info2, time as StartTime, username, replace(info1,'Root\','') as AccountName, 
  Case When info2 not like '%;DataBase=%' Then substr(info2, instr(info2, 'ApplicationType=') +16 , instr(info2, ';Dst') -17) Else substr(info2, instr(info2, 'ApplicationType=') +16 , instr(info2, ';DataBase=') -17) 
  End as ConnectionComponent, substr(info2, instr(info2, 'DstHost=') +8, (instr(info2, ';Pro') +- instr(info2, 'DstHost=') - 8)) as TargetHost, substr(info2, instr(info2, 'User=') +5, length(info2) - instr(info2, 'User=') -5) as TargetUser, 
     substr(info2, instr(info2, 'PSMID=') +6, (instr(info2, ';Session') - instr(info2, 'PSMID=') - 6)) as PSMID, 
     substr(info2, instr(info2, 'SessionID=') +10, (instr(info2, ';Src') - instr(info2, 'SessionID=') -10)) as SessionID, 
     substr(info2, instr(info2, 'SrcHost=') +8, (instr(info2, ';User') - instr(info2, 'SrcHost=') -8)) as PSMHost, 
     Null as SessionDuration from logs 
where code in (300) and info2 != 0) a left join (select time as EndTime,
     substr(info2, instr(info2, 'SessionDuration=') +16, (instr(info2, ';SessionID') - instr(info2, 'SessionDuration=') - 16)) as SessionDuration, 
     substr(info2, instr(info2, 'SessionID=') +10, (instr(info2, ';Src') - instr(info2, 'SessionID=') -10)) as SessionID 
from logs 
where code in (302) and info2 != 0) b on a.SessionID = b.SessionID left join (Select 'Yes' as PSMDisconnectFailed, time, 
     substr(info2, instr(info2, 'SessionID=') +10, (instr(info2, ';Src') - instr(info2, 'SessionID=') -10)) as SessionID, 
     substr(info2, instr(info2, 'SessionDuration=') +16, (instr(info2, ';SessionID') - instr(info2, 'SessionDuration=') - 16)) as SessionDuration, RequestReason 
 from logs where code in (303) and info2 != 0) c on a.SessionID = C.SessionID

任何人都知道如何进一步解决/调查此问题?

编辑#1:我正在使用以下命令在我的C#代码中建立连接:

        public static SQLiteConnection connectToDB()
    {
        dbConnection = new SQLiteConnection("Data Source = data\\LOGS.db; Version = 3;");
        dbConnection.Open();
        return dbConnection;
    }

编辑#2:升级SQLite Studio(现在使用SQLite版本3.24.0)后,我看到与System.Data.SQLite SQLit v3.27.0版本相同的解释查询计划输出。 注意:“自动覆盖索引”部分现在也已丢失。

7   0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
14  0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
48  0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)

1 个答案:

答案 0 :(得分:0)

非常有趣:将查询转换为视图并运行select * from myview后,查询很快。解释查询计划现在具有以下输出:

id  parent  notused detail
3   0   0   MATERIALIZE 2
7   3   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
44  0   0   MATERIALIZE 3
48  44  0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
92  0   0   SEARCH TABLE logs USING INDEX i_Logs (Code=?)
112 0   0   SEARCH SUBQUERY 2 AS b USING AUTOMATIC COVERING INDEX (SessionID=?)
140 0   0   SEARCH SUBQUERY 3 AS c USING AUTOMATIC COVERING INDEX (SessionID=?)
157 0   0   USE TEMP B-TREE FOR GROUP BY
259 0   0   USE TEMP B-TREE FOR ORDER BY

我不确定为什么使用视图时EQP会发生变化,但是我现在很高兴,因为它工作的很好而且非常快:-)

非常感谢@Carlos Cavero格式化我的代码。

相关问题