布尔记录的查询效率

Posted

技术标签:

【中文标题】布尔记录的查询效率【英文标题】:query efficiency for boolean record 【发布时间】:2015-04-29 09:23:50 【问题描述】:

我有一些带有布尔列的表,例如一个活动列来指示用户是否处于活动状态,然后查询我使用的所有非活动用户

select * from users where active = 0

我的大多数用户都很活跃。我明白在没有帮助的情况下,查询需要检查每条记录,这在我的情况下效率低且速度相当慢。我有另一个带有布尔列的表,比如一个已处理的列来记录订单是否已被处理并查询所有未处理的订单,

select * from orders where processed = 0

我正在考虑添加一个帮助表来记录那些不活跃的用户和未处理的订单,例如,

CREATE TABLE IF NOT EXISTS failedRecord (tablename text, row integer) ; //row will be rowid

我真的不喜欢这种自制的解决方案。我更喜欢使用数据库提供的解决方案,但我不确定在布尔列上使用索引是否有帮助。 B/C 我认为索引是通过创建一个单独的索引表来实现的,该索引表将从列创建的键映射到索引表中的行索引。对于布尔列,因为值只能是 0 或 1,我认为映射效率不高。

我使用 sqlite,但我认为其他数据库也会有问题。


更新了我的问题。

我的大多数用户都处于活动状态,并且大部分订单都已处理,即在我的情况下,这里只有几行是 0,所以经过仔细考虑,索引可能是有效的。是这样吗?

【问题讨论】:

如果您需要如此密集地访问布尔值,如何将它们全部加载为布尔值,例如一个排序的 ArrayList,在启动时。所以你有一个内存缓存。并且只在必要时更新数据库。 我就是这么做的。但我在问任何有效的方法来“加载所有这些”。谢谢 【参考方案1】:

如果大多数用户处于活动状态,或者大多数订单都已处理,那么匹配的行数很少,您可以通过索引processed 列来加快第二次查询。 (如果您有 SQLite 3.8.0 或更高版本,您可以避免使用 partial index 来索引已处理的订单。) 与手动创建帮助表相比,使用索引要快得多且更易于维护。

如果您使用反向条件(以便大多数行匹配),则无论如何您都必须访问表的几乎所有页面。 在这种情况下,没有比按顺序阅读所有页面更快的机制了。

【讨论】:

我的大多数用户都处于活动状态,并且大多数订单都已处理,这就是为什么我说我正在考虑添加另一个表来记录它们。我更新了我的问题。谢谢! 如果大多数记录都匹配,则检查所有记录是有效的。 但在我的情况下,大多数都不匹配,不是吗? 确实如此。我说的是大多数行匹配,因为我误读了原始问题。 我确实考虑过使用索引,但由于它只有布尔值(0 或 1),它真的有帮助吗?【参考方案2】:

我发现在 sqlite 邮件列表Index on BOOLEAN field 上提出并回答了这个问题。我希望他们是对的。

引用,“如果所有可能的值均等分布,并且您经常查找特定值,那么即使您只有两个可能的值,索引也会有所帮助。如果您几乎拥有所有 '2011' 行,并且您重新搜索“2011”,那么索引将无济于事......

实际上,盈亏平衡点大约是 1/10:如果您是 选择表中 10% 或更少的记录;否则,线性扫描是 更快。”

“当且仅当 a) FLAG=1 的记录比 FLAG=0 的记录多(反之亦然)时,这可能会有所帮助;并且 b) 大多数时候,您正在查找属于小子集。例如,如果有少量“活动”或最近需要处理的记录,以及大量“已处理”记录的存档。”

【讨论】:

以上是关于布尔记录的查询效率的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 查询记录是否存在的效率问题

mysql随机查询记录的高效率方法

mysql Count 查询记录总条数,效率很慢

mysql Count 查询记录总条数,效率很慢

MySQL使用rand 随机查询记录效率测试

查询效率 - 从表中选择 2 个最新的“组/批次”记录