如何索引 SQLite 表中的树?

Posted

技术标签:

【中文标题】如何索引 SQLite 表中的树?【英文标题】:How can I index a tree in a SQLite Table? 【发布时间】:2011-12-31 07:15:11 【问题描述】:

我有一个包含以下字段的表格:

id VARCHAR(32) 主键, 父 VARCHAR(32), 名称 VARCHAR(32)

parent 是引用同一个表的外键。该结构生成一棵树。这棵树应该复制文件系统树。问题是从路径中查找 id 很慢。因此我想建立一个索引。这样做的最佳方法是什么?

示例数据:

id 父母姓名 -------- ----------- ---------- 1 NULL 根 2 1 英尺 3 1 巴 4 3 巴兹 5 4 aii

将索引到:

id 父母姓名 -------- ----------- ---------- 1 NULL 根 2 1 根/foo 3 1根/条 4 3 根/bar/baz 5 4根/bar/baz/aii

我目前正在考虑使用临时表,并在代码中手动运行一系列插入源来构建索引。 (我将其设为临时的原因是,如果从 Windows 系统访问此数据库,则路径需要反斜杠,而从 *nix 需要正斜杠)。有没有替代方案?

【问题讨论】:

【参考方案1】:

所以,你有一个函数可以做这样的事情(伪代码):

int getId(char **path) 
    int id = 0;
    int i;
    char query[1000];

    for (i = 0; path[i] != NULL; i++) 
        sprintf(query, "select id from table where parent = %d and name = '%s'", id, name);
        id = QuerySimple(query);
        if (id < 0)
           break;
    
    return id;

查看查询,您需要列(父、名称)上的(非唯一)索引,但也许您已经拥有它。

可以像你说的那样使用(临时)表,注意你可以在程序中更改路径分隔符,避免 windows 和 unix 需要不同的表。您还需要使附加表与主表保持同步。如果更新/删除/插入很少见,而不是表,您可以简单地保留已查找数据的内存缓存,并在更新发生时清除缓存(如果需要,您也可以对缓存进行部分删除)。在这种情况下,您还可以读取更多数据(例如,给定父级读取所有子级)以更快地填满缓存。在极端情况下,您可以读取内存中的整个表格并在那里工作!这取决于您拥有多少数据、您的典型访问模式(读取次数、写入次数)以及部署环境(您有空闲的 RAM 吗?)。

【讨论】:

以上是关于如何索引 SQLite 表中的树?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过索引(而不是 id)在 SQLite 中获取一行

SQLite 中的主键是不是需要索引?

SQLite 中的主键是不是需要索引?

如何重命名 SQLite 数据库表中的列?

在 sqlite 中选择特定的索引行

如何从 SQLite 中的表中选择最新的 100 个不同条目?