使用SQLite 3.19.2,我遇到了奇怪的情况。
我的应用程序执行的其中一个查询在我的应用程序内运行时需要很长时间(100+秒)。使用sqlite3 shell,相同的查询需要0.5秒。
我使用SQLite的自定义版本,静态链接到我的应用中。 shell的版本来自我的自定义编译,因此这不是编译的问题。
我使用的是多线程,但是我已经设法重现了这个问题的单线程。
使用perf
我已经确定大部分CPU时间花费在sqlite3VdbeExec
而不是我的任何代码中(例如,读取每个返回行的字段的代码)。 )
查询为sqlite3_prepare_v2
并带有绑定参数。我已经复制了下面的查询以及一个没有出现性能问题的类似查询。
还有其他人见过这样的事吗?
慢速查询(应用程序中100 + s,shell中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;
QUERY PLAN(无论是在应用程序中还是在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
SIMILAR QUERY(应用程序为0.5秒,shell为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' );
答案 0 :(得分:0)
我认为这是SQLite
中的错误。在准备好的语句中使用查询时,我将问题跟踪到CASE
子句中的ORDER BY
语句。
当我删除一个或另一个语句时,查询再次快速运行。整理没有任何区别。
这似乎不是准备好的语句的一般问题,我有其他类似结构的查询,并且它们正常工作。因此,我无法创建一个简单,可重现的例子来说明问题。
最终我必须通过手动替换查询中的变量来解决这个问题,以避免使用预准备语句。