我有一个包含大量日志消息的SQLite数据库。
我想在列表视图中显示它(使用wxWidgets)。
用户可以对列表重新排序(通过按列标题),对结果集应用过滤器,并使用滚动条将其作为常规列表导航。用户还可以在列表中选择一个或多个条目并将其删除。
我有一个虚拟列表模型:列表视图向模型询问特定行的内容。模型使用当前过滤条件和顺序发出select-query,并从结果中返回相应的行。
为了加快速度,我保留了结果的页面缓存:当请求一行时,我使用LIMIT和OFFSET获取整页(~100行)并返回页面中的特定行。我存储了许多页面,下次请求一行时,我首先查看它是否在其中一个缓存页面中可用。事实证明,即使使用 lot 条目(50k +),这项技术也能快速响应。
问题
我的问题是如何处理更新/插入/删除。我每个都有一个触发器,因此每当插入/更新/删除发生时都会通知模型。触发器还会告知模型受影响条目的ID(主键)。
我的第一个版本只是在每次触发后完全重置了模型。这不是很快,但足够快。问题是,如果用户选择了一行或几行,则选择丢失。
模型的基类(wxDataViewVirtualListModel)包含在发生更改时应调用的方法:
如果我使用它们,选择问题就会解决,但是存在问题:
第一个问题可以通过创建一个检查条目是否属于集合的方法来解决。它的行为必须与SQL条件完全相同,但它是可行的。
第二个问题我根本不知道如何解决。
我使用了伪造的(0行或最后一行)行号来强制更新视图,但问题是如果在选择之前插入/删除了行,则选择后指向错误的行,并且等等。
你会怎么做?保留一个包含内存中所有条目的高级数据结构?此问题与另一个问题有关: Display large result set
答案 0 :(得分:1)
我会围绕两个不同的SELECT操作设计它,一个只获取所有行的主键和一个时间戳(INSERT / UPDATE),另一个获取单页行的所有数据。在现代机器上,即使对于几十万行,保留内存中主键和时间戳的完整列表也不应该成为问题。
每当过滤条件发生变化或触发器触发时,我都会再次检索主键和时间戳列表。该模型维护主键列表和匹配的时间戳,模型与新列表之间的比较显示需要插入,无效或删除哪些行。时间戳已更改的缓存行将从缓存中删除,无需再次检索具有相同时间戳的缓存行。当缓存太大时,将删除最旧的缓存条目。
可以通过其主键值识别列表的选择,因此除非已删除该行,否则在更改模型后,即使它现在处于完全不同的位置,也始终可以重新选择该行。我发现这比订单更改时保持相同的行位置更直观,选择完全不同的行。
修改强>
这适用于来自其他数据库客户端的并发数据更改,我已经以这种方式为使用Firebird数据库服务器的应用程序实现了它。如果无法从外部更改数据,则可能无需始终检索主键和时间戳的完整列表。