使用 SQLite 3.19.2,我遇到了一个奇怪的情况。
在我的应用程序中运行时,我的应用程序执行的查询之一需要很长时间(100 秒以上)。使用 sqlite3 shell,同样的查询需要 0.5 秒。
我正在使用 SQLite 的自定义版本,静态链接到我的应用程序。shell 的版本来自我的自定义编译,所以这不是编译的问题。
我使用了多个线程,但是我已经设法以单线程方式重现这个问题。
使用perf
我已经确定大部分 CPU 时间花在sqlite3VdbeExec
而不是花在我的任何代码中(例如读取每个返回行的字段的代码。)
查询sqlite3_prepare_v2
带有绑定参数。我已经复制了下面的查询以及没有表现出性能问题的类似查询。
有没有其他人看到过这样的事情?
慢查询(应用程序中 100+ 秒,外壳程序中 0.5 秒):
SELECT DISTINCT
Track.*
FROM
TrackGenres,
TrackFirstArtist,
Track
WHERE
TrackFirstArtist.id = Track.id AND
TrackGenres.id = Track.id AND
TrackGenres.genreID = 328
ORDER BY
(CASE WHEN 1 = 1 THEN TrackFirstArtist.artistName COLLATE ENGLISH END) ASC,
(CASE WHEN 1 != 1 THEN TrackFirstArtist.artistName COLLATE ENGLISH END) DESC
LIMIT 50
OFFSET 0;
查询计划(无论是在应用程序中还是在 shell 中运行,计划都是相同的):
2 0 0 SEARCH TABLE TrackGenre USING COVERING INDEX sqlite_autoindex_TrackGenre_1 (genreID=?)
3 0 1 SEARCH TABLE WorkGenre USING COVERING INDEX sqlite_autoindex_WorkGenre_1 (genreID=?)
3 1 0 SEARCH TABLE TrackWork USING COVERING INDEX sqlite_autoindex_TrackWork_1 (workID=?)
1 0 0 COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)
4 0 0 SCAN TABLE TrackArtist USING INDEX idx_TrackArtist_trackID
4 1 1 SEARCH TABLE Artist USING INTEGER PRIMARY KEY (rowid=?)
0 0 0 SCAN SUBQUERY 1
0 1 2 SEARCH TABLE Track USING INTEGER PRIMARY KEY (rowid=?)
0 2 1 SEARCH SUBQUERY 4 USING AUTOMATIC COVERING INDEX (id=?)
0 0 0 USE TEMP B-TREE FOR DISTINCT
0 0 0 USE TEMP B-TREE FOR ORDER BY
类似查询(应用程序 0.5 秒,外壳程序 0.5 秒):
SELECT
COUNT (Track.id)
FROM
TrackGenres,
TrackFirstArtist,
Track
WHERE
TrackFirstArtist.id = Track.id AND
TrackGenres.id = Track.id AND
TrackGenres.genreID = 328 AND
( TrackFirstArtist.artistName >= 'a' AND TrackFirstArtist.artistName < 'b' );
我相信这是SQLite
. 我跟踪这个问题下到CASE
中陈述ORDER BY
在一份声明中使用查询时子句。
当我删除一个或另一个语句时,查询再次快速运行。整理没有任何区别。
这似乎不是准备好的语句的普遍问题,我还有其他具有类似结构的查询,并且它们可以正常工作。因此,我一直无法创建一个简单的、可重现的示例来说明问题。
最终我不得不通过手动替换查询中的变量来解决这个问题,以避免使用准备好的语句。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句