使用 GROUP BY 的索引

Posted

技术标签:

【中文标题】使用 GROUP BY 的索引【英文标题】:Use index for GROUP BY 【发布时间】:2014-04-02 13:27:43 【问题描述】:

我有以下疑问:

SELECT * FROM messages GROUP BY peer

(实际上,连接更复杂,但为了简单起见,我在这里省略了它们) 问题是 SQLite 不使用任何索引并且总是对表执行完整扫描。不出所料,它在小型数据集上运行速度很快,但在包含数千行的大表上运行速度明显较慢。这是 EXPLAIN QUERY PLAN 命令的输出:0|0|0|SCAN TABLE messages USING INDEX messages_peer_mid (~1000000 rows) 尽管它说“使用索引”,但它仍然执行完整扫描。有什么方法可以让 SQLite 为这个查询使用索引,或者最好放弃 GROUP BY 并寻找其他方法?

【问题讨论】:

【参考方案1】:

该计划会考虑数据量并执行扫描,因为它的算法可能会得出结论,这样做会更快。

其他 cmets,您的查询没有 WHERE 条件并且您正在返回所有列,那么您为什么不期望进行表扫描?

【讨论】:

我认为他说他的查询只是为了简单起见而写成这样。 我只能评论我所知道的......据我所知,他的实际查询没有 where 子句或仍然(显然)需要扫描的子句【参考方案2】:

索引有助于从表中选择记录(使用WHERE 子句或作为JOIN 操作的结果)。 GROUP BY 在一组记录被选中并从表中检索到之后执行。它不能通过索引来辅助。

如果您想了解更多关于您的查询中有哪些选项可用于索引,请发布整个查询。

此外,您注意到您提供的 SQL 是您正在运行的代码的符号表示,但如果您真的在语句中使用 * 或除 peer 之外的任何非聚合字段名称你可能得不到你想要的结果。

最后,您问“最好放弃 GROUP BY 并寻找其他方法?” GROUP BY 用于 SQL 中的特定函数(从非聚合数据生成新的聚合结果集)。如果这是您的目标,GROUP BY 可能是最好的解决方案(因为它遵从数据库引擎,该引擎经过高度优化并且认识到数据库统计信息来决定如何检索和处理数据)。如果这不是您的目标,并且您尝试使用 GROUP BY 作为其他功能的“方法”来做其他事情,请告诉我们您实际想要实现的目标。

【讨论】:

我使用此查询从包含消息的表中获取聊天列表。实际上,我只需要每次聊天中最后一条消息的 ID(这是我在问题中的错误);然后我可以使用子查询选择详细信息,这将很快,因为它使用索引。 “其他方法”是指使用这些 ID 创建一个单独的表并使用触发器更新它。 您是在关注来自 所有 聊天的最新消息,还是只在应用程序的任何给定屏幕上关注您感兴趣的聊天子集。如果您需要帮助优化,请编辑您的原始问题,使其至少具有完整的 SQL(表结构也可能是相关的)。

以上是关于使用 GROUP BY 的索引的主要内容,如果未能解决你的问题,请参考以下文章

为啥 postgresql 不使用我的 group by 聚合索引?

MYSQL性能调优05_覆盖索引索引下推如何选择合适的索引Order by与Group by优化索引设计原则

Group BY 查询使用索引,但窗口函数查询不使用

mysql group by 能用到索引么

mysql优化 之 group by索引松散扫描和紧凑扫描

为 Group By 字段创建索引?