【发布时间】:2019-03-17 21:04:20
【问题描述】:
我有一个在同一张表上运行多个联接的查询。它加入了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=?)
请注意,没有使用自动覆盖索引。
我尝试使用分析并为 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 版本相同的解释查询计划输出。 注意:“AUTOMATIC COVERING INDEX”部分现在也不见了。
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=?)
【问题讨论】:
-
这两个程序使用的是什么版本的 sqlite(它们可能不一样,尽管基于 EQP 输出都是旧的)。
-
你能重新格式化你的帖子,让 select 是可读的,而不是一个巨大的长行吗?
-
嗨@Shawn。运行命令“select sqlite_version();”时- 我看到以下输出: SQLiteStudio:3.15.0 C# 代码:3.27.2 我正在使用 System.Data.SQLite 1.0.110 和 SQLite Studio v3.1.1。
-
嗨@Shawn。我更新了 SQLite Studio,现在在运行“select sqlite_version();”时看到以下输出:3.24.0 此外,自从更新以来,解释查询计划现在看起来与我在 C# 3.27.2 中看到的完全一样查询计划:0 0 SEARCH TABLE logs USING INDEX i_Logs (Code=?) 0 0 SEARCH TABLE logs USING INDEX i_Logs (Code=?) 0 0 SEARCH TABLE logs USING INDEX i_Logs (Code=?) 注意:“SEARCH SUBQUERY 1 AS b USING AUTOMATIC COVERING INDEX (SessionID=?)" 部分现在也不见了。
-
您可以找到在线工具来将 SQL 格式化为人类可读的格式。两个版本之间的变更日志中有一些内容可能适用,但是您现在的查询仍然是一个无法阅读的混乱,我不能肯定地说。
标签: sqlite