Tentative fix for bad query perf with recent sqlite versions: limit 1 seems to be culprit

This commit is contained in:
emeric
2025-07-13 00:06:10 +02:00
parent 59e85ee424
commit 6704762cc3
6 changed files with 116 additions and 15 deletions
+87 -1
View File
@@ -114,7 +114,7 @@ namespace lms::db
std::string table; std::string table;
std::string foreignTable; std::string foreignTable;
// see https://www.sqlite.org/pragma.html#pragma_foreign_key_check for exepcted result // see https://www.sqlite.org/pragma.html#pragma_foreign_key_check for expected result
while (statement->nextRow()) while (statement->nextRow())
{ {
foreignKeyConstraintsPassed = false; foreignKeyConstraintsPassed = false;
@@ -132,6 +132,57 @@ namespace lms::db
return foreignKeyConstraintsPassed; return foreignKeyConstraintsPassed;
} }
std::optional<int> getPageSize(Wt::Dbo::SqlConnection& connection)
{
auto statement = connection.prepareStatement("PRAGMA page_size");
statement->execute();
std::optional<int> res;
while (statement->nextRow())
{
assert(!res);
int value{};
if (statement->getResult(0, &value))
res = value;
break;
}
return res;
}
std::optional<int> getCacheSize(Wt::Dbo::SqlConnection& connection)
{
auto statement = connection.prepareStatement("PRAGMA cache_size");
statement->execute();
std::optional<int> res;
while (statement->nextRow())
{
assert(!res);
int value{};
if (statement->getResult(0, &value))
res = value;
break;
}
return res;
}
void getCompileOptions(Wt::Dbo::SqlConnection& connection, std::function<void(std::string_view compileOption)> callback)
{
auto statement = connection.prepareStatement("PRAGMA compile_options");
statement->execute();
std::string res;
while (statement->nextRow())
{
res.clear();
if (statement->getResult(0, &res, static_cast<int>(res.capacity())))
callback(res);
}
}
} // namespace } // namespace
std::unique_ptr<IDb> createDb(const std::filesystem::path& dbPath, std::size_t connectionCount) std::unique_ptr<IDb> createDb(const std::filesystem::path& dbPath, std::size_t connectionCount)
@@ -157,6 +208,13 @@ namespace lms::db
_connectionPool = std::move(connectionPool); _connectionPool = std::move(connectionPool);
executeSql("PRAGMA temp_store=MEMORY");
executeSql("PRAGMA cache_size=-8000");
executeSql("PRAGMA automatic_index=0");
logPageSize();
logCacheSize();
logCompileOptions();
if (checkType == "quick") if (checkType == "quick")
{ {
performQuickCheck(); performQuickCheck();
@@ -199,6 +257,34 @@ namespace lms::db
return *tlsSession; return *tlsSession;
} }
void Db::logPageSize()
{
ScopedConnection connection{ *_connectionPool };
const std::optional<int> pageSize{ getPageSize(*connection) };
if (pageSize)
LMS_LOG(DB, INFO, "Page size set to " << *pageSize);
}
void Db::logCacheSize()
{
ScopedConnection connection{ *_connectionPool };
const std::optional<int> cacheSize{ getCacheSize(*connection) };
if (cacheSize)
LMS_LOG(DB, INFO, "Cache size set to " << *cacheSize);
}
void Db::logCompileOptions()
{
ScopedConnection connection{ *_connectionPool };
LMS_LOG(DB, INFO, "Sqlite3 compile options:");
getCompileOptions(*connection, [](std::string_view compileOption) {
LMS_LOG(DB, INFO, compileOption);
});
}
void Db::performQuickCheck() void Db::performQuickCheck()
{ {
ScopedConnection connection{ *_connectionPool }; ScopedConnection connection{ *_connectionPool };
+3
View File
@@ -49,6 +49,9 @@ namespace lms::db
core::RecursiveSharedMutex& getMutex() { return _sharedMutex; } core::RecursiveSharedMutex& getMutex() { return _sharedMutex; }
Wt::Dbo::SqlConnectionPool& getConnectionPool() { return *_connectionPool; } Wt::Dbo::SqlConnectionPool& getConnectionPool() { return *_connectionPool; }
void logPageSize();
void logCacheSize();
void logCompileOptions();
void performQuickCheck(); void performQuickCheck();
void performIntegrityCheck(); void performIntegrityCheck();
void performForeignKeyConstraintsCheck(); void performForeignKeyConstraintsCheck();
+1
View File
@@ -58,6 +58,7 @@ namespace lms::db::utils
if (range) if (range)
{ {
query.limit(static_cast<int>(range->size)); query.limit(static_cast<int>(range->size));
if (range->offset != 0)
query.offset(static_cast<int>(range->offset)); query.offset(static_cast<int>(range->offset));
} }
} }
@@ -91,7 +91,7 @@ namespace lms::db
} }
if (params.imageType.has_value()) if (params.imageType.has_value())
query.where("+t_e_i_l.type = ?").bind(params.imageType.value()); // hack: type is a bad way to reduce the result space query.where("t_e_i_l.type = ?").bind(params.imageType.value());
} }
switch (params.sortMethod) switch (params.sortMethod)
@@ -142,9 +142,10 @@ namespace lms::scanner
params.setRelease(release->getId()); params.setRelease(release->getId());
params.setImageType(db::ImageType::FrontCover); params.setImageType(db::ImageType::FrontCover);
params.setSortMethod(db::TrackEmbeddedImageSortMethod::DiscNumberThenTrackNumberThenSizeDesc); params.setSortMethod(db::TrackEmbeddedImageSortMethod::DiscNumberThenTrackNumberThenSizeDesc);
params.setRange(db::Range{ .offset = 0, .size = 1 }); db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) {
if (!artwork)
db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) { artwork = db::Artwork::find(session, image->getId()); }); artwork = db::Artwork::find(session, image->getId());
});
} }
if (artwork) if (artwork)
@@ -156,9 +157,10 @@ namespace lms::scanner
params.setRelease(release->getId()); params.setRelease(release->getId());
params.setImageType(db::ImageType::Media); params.setImageType(db::ImageType::Media);
params.setSortMethod(db::TrackEmbeddedImageSortMethod::DiscNumberThenTrackNumberThenSizeDesc); params.setSortMethod(db::TrackEmbeddedImageSortMethod::DiscNumberThenTrackNumberThenSizeDesc);
params.setRange(db::Range{ .offset = 0, .size = 1 }); db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) {
if (!artwork)
db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) { artwork = db::Artwork::find(session, image->getId()); }); artwork = db::Artwork::find(session, image->getId());
});
} }
return artwork; return artwork;
@@ -65,8 +65,11 @@ namespace lms::scanner
params.setTrack(track->getId()); params.setTrack(track->getId());
params.setImageType(db::ImageType::FrontCover); params.setImageType(db::ImageType::FrontCover);
params.setSortMethod(db::TrackEmbeddedImageSortMethod::SizeDesc); params.setSortMethod(db::TrackEmbeddedImageSortMethod::SizeDesc);
params.setRange(db::Range{ .offset = 0, .size = 1 });
db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) { res = db::Artwork::find(session, image->getId()); }); db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) {
if (!res)
res = db::Artwork::find(session, image->getId());
});
} }
if (res) if (res)
@@ -92,8 +95,11 @@ namespace lms::scanner
params.setTrack(track->getId()); params.setTrack(track->getId());
params.setImageType(db::ImageType::Media); params.setImageType(db::ImageType::Media);
params.setSortMethod(db::TrackEmbeddedImageSortMethod::SizeDesc); params.setSortMethod(db::TrackEmbeddedImageSortMethod::SizeDesc);
params.setRange(db::Range{ .offset = 0, .size = 1 });
db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) { res = db::Artwork::find(session, image->getId()); }); db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) {
if (!res)
res = db::Artwork::find(session, image->getId());
});
} }
if (res) if (res)
@@ -111,8 +117,11 @@ namespace lms::scanner
params.setDiscNumber(discNumber); params.setDiscNumber(discNumber);
params.setImageType(db::ImageType::Media); params.setImageType(db::ImageType::Media);
params.setSortMethod(db::TrackEmbeddedImageSortMethod::TrackNumberThenSizeDesc); params.setSortMethod(db::TrackEmbeddedImageSortMethod::TrackNumberThenSizeDesc);
params.setRange(db::Range{ .offset = 0, .size = 1 });
db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) { res = db::Artwork::find(session, image->getId()); }); db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) {
if (!res)
res = db::Artwork::find(session, image->getId());
});
} }
return res; return res;