1

我的应用程序是数据库驱动的。每行包含我在 UIWebView 中显示的主要内容列。大多数行(内容列)都有对 image1 的引用和一些对 image2 的引用。我将这些转换为 base64 并将图像字符串添加到行中。但是,如果任一图像发生更改,则意味着我必须返回所有行并更新 base64 字符串。

我可以在行内容中提供一个唯一的字符串,例如 {image1}。这意味着我必须搜索该行的整个内容并替换为图像的 base64 版本。这些图像也始终位于行内容的底部。不确定如何在替换之前先浏览所有内容会影响性能。有一个更好的方法吗?

4

2 回答 2

1

我希望我能正确理解你的问题。

如果图像不是很大,那么使用 like 关键字可能是可以的,如下所示:

sqlite3_stmt *statement = nil;
if(statement == nil)
{
    const char *sql = [[NSString stringWithFormat:@"SELECT imageContent FROM imageDatabase WHERE imageContent LIKE '%@%@%@'", @"%", imageValue, @"%"] UTF8String];
    if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) != SQLITE_OK) {
        //NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(db));
        return;
    }
}
while (sqlite3_step(statement) == SQLITE_ROW) {
    // query was successful
    // perform some action on the resulting data
}
sqlite3_finalize(statement);
statement = nil;

如果您设置 imageValue = image1、image2 或其他任何值,这将为您提供您正在从数据库中查找的项目,而无需在代码中进行字符串操作。我假设你知道 SQL,如果这是多余的信息,很抱歉,但上面将搜索你的 imageDatabase 以查找包含 image1、image2 imageValue 的任何内容。找到该行后,您可以更新它,或者您可以将 WHERE 子句与 UPDATE SQL 语句一起使用,但我发现这有点危险,因为可能会在不先检查内容以确保不经意地更新多行的情况下这就是你想要的。

此外,如果您正在使用它进行数据库更新,您会发现通过使用以下事务包装插入和更新可以显着提高性能:

const char *sql = "BEGIN TRANSACTION;";
    char *errMsg;
    sqlite3_exec(db, sql, nil, 0, &errMsg);

const char *commit = "COMMIT;";
    sqlite3_exec(db, commit, nil, 0, &errMsg);

它在执行之前准备和优化您的查询。我已经看到插入和更新查询的速度是事务的两倍。

如果数据库非常大,这将对性能产生重大影响,但是在内存中进行字符串操作会产生很大的内存成本。如果您使用 SQLite LIKE 方法,则字符串搜索以串行方式在磁盘上完成,并且内存命中较少。

找到特定项目后,您可以对特定字符串进行正则表达式搜索和替换,从而使代码的内存占用更小。

于 2009-05-14T05:02:31.590 回答
0

为什么不在表中使用 image_ID(唯一整数)和 image_data(blob)中的图像?然后在您的主表中,仅存储 image_ID,如果您需要实际图像,请进行连接?

关于您的问题的另一种解释(如果该答案对您没有意义),为什么不将内容分为三个字段:图像之前的内容、图像和之后的内容。存储中间部分的 image_ID(不是数据——通过图像表上的 sql JOIN 获取)。然后通过连接构建最终内容。

于 2009-03-21T19:37:10.983 回答