3

我正在使用带有“状态”列的表,它通常只包含 2 或 3 个不同的值。有时,当这个表包含几百万行时,下面的 SQL 语句会变慢(我假设完成了全表扫描):

SELECT state, count(*) FROM mytable GROUP BY state

我希望得到这样的东西:

disabled |  500000
enabled  | 2000000

(基本上我想知道有多少项目被“启用”以及有多少项目被“禁用” - 实际上这是一个数字而不是我实际应用程序中的文本)

我想为我的状态列添加索引是没有用的,因为在那里只能找到很少的不同值。我还有什么其他选择?

还有一个“时间戳”列(带有索引)。理想情况下,如果我添加,该解决方案也应该可以正常工作:

WHERE timestamp BETWEEN x AND y

现在我正在使用 SQLite3 数据库,但看起来其他数据库引擎并没有太大的不同,因此其他数据库引擎的解决方案也可能很有趣。

谢谢!

4

1 回答 1

2

我会在时间戳,状态(按该顺序)上放置一个覆盖索引。理由是:

  • 时间戳上的条件将比状态更具选择性

  • 如果状态还在索引中(即覆盖索引),引擎只需要对索引本身进行范围扫描(无需支付随机I/O来访问表的主要数据)。

注意:如果时间戳范围太宽,尽管有索引,它也会变慢。因为随机 I/O 比顺序 I/O 更昂贵,所以索引范围扫描会比表扫描更昂贵。根据经验,如果您需要扫描超过 10% 的表,引擎应该考虑保持表扫描并忽略索引。我注意到 sqlite 足够聪明,可以支持这种优化。

于 2012-10-30T17:49:41.060 回答