【问题标题】:Static vs non-static prepared statment in SQLite C APISQLite C API 中的静态与非静态准备语句
【发布时间】:2014-03-03 21:21:24
【问题描述】:

我正在使用 C 和 SQL 开发一个终端应用程序,用于标记文件。文件/标签关系保存在 SQLite 3 数据库中。到目前为止,我一直在使用静态分配的准备好的语句,这些语句在每次调用包装函数时都会被重置和绑定。最近我正在用valgrind 测试内存泄漏等,它抱怨很多,因为显然包装器中的静态sqlite3_stmt 在程序终止时没有被释放。这也会导致数据库无法正确关闭(因为未完成的语句)。

这样做的最初原因是性能。我在the C interface intro 中读到,重用准备好的语句对性能非常有好处。

在现有的预处理语句上使用 sqlite3_reset() 而不是创建新的预处理语句可以避免对 sqlite3_prepare() 的不必要调用。在许多 SQL 语句中,运行 sqlite3_prepare() 所需的时间等于或超过 sqlite3_step() 所需的时间。因此,避免调用 sqlite3_prepare() 可以显着提高性能。

这里有一些代码来显示我在做什么:

int tag_file(const char *file, const char *tag)
{
    static sqlite3_stmt *sql_prep = NULL;
    static const char *sql_str = "INSERT OR IGNORE INTO Tag VALUES (?, ?);";

    // Prepare if null, else reset
    prepare_or_reset(&sql_prep, sql_str);

    if (sqlite3_bind_text(sql_prep, 1, file, -1, SQLITE_STATIC) != SQLITE_OK ||
        sqlite3_bind_text(sql_prep, 2, tag, -1, SQLITE_STATIC) != SQLITE_OK)
        return ERROR;

    if (sqlite3_step(sql_prep) != SQLITE_DONE)
        return ERROR;

    return SUCCESS;
}

我尝试过的,将满足valgrind,但完全错过了重用准备好的语句的性能增益是使sql_prep非静态并在函数末尾调用sqlite3_finalize(sql_prep),但我猜这个性能更差。我可以以一种优雅的方式只准备一次语句而不会导致内存泄漏吗?

我开始担心的另一件事是内存消耗。将来我计划为这个应用程序创建一个 GUI,这将使所有这些在内存中保存更长时间。性能提升可能会更大,但从第一次调用退出时,该语句将只是坐在堆上。这是公平的space-time tradoff吗?

编辑:将所有“静态”准备好的语句保存在一个全局数组中,我可以释放 atexit,这会是丑陋/奇怪吗?

【问题讨论】:

    标签: c sqlite


    【解决方案1】:
    1. 必须在关闭数据库之前完成所有语句。

      如果在 tag_file 等函数之外不知道这些语句,则这是不可能的。 您应该有一个全局语句列表,并让prepare_or_reset 函数将语句动态添加到该列表中。

    2. 准备好的语句很小;与 GUI 库分配的所有东西没有可比性。您很可能甚至不会注意到它们的内存使用情况。

      但是,如果您不经常执行准备好的语句以致准备时间很明显,那么它们并不会显着提高速度。因此,这两种方式都可能无关紧要。 ☺

    【讨论】:

      【解决方案2】:

      你提到了两个问题。

      1. 第一个本质上是如何管理准备好的语句。

        在这里重新设计你的int tag_file(const char *file, const char *tag) 函数似乎是合适的。

        您要么将 stmt 保持高一级,然后每次都将其传递给函数。然后你可以在程序的最后进行清理。

        另一种方法是定义函数的语义,给它特殊的标记函数(可能只是(NULL, NULL)),使函数释放语句。

      2. 第二个问题是堆大小的问题。只要你没有成百上千个准备好的 stmts,我认为你可以一直拥有它,因为它可能只需要几个字节。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-17
        • 1970-01-01
        • 2021-10-20
        • 1970-01-01
        • 1970-01-01
        • 2014-03-02
        相关资源
        最近更新 更多