google-cloud-platform - Cloud Spanner 不应该使用二级索引
问题描述
使用主键快速执行的现有查询在没有通知的情况下大幅减慢(10ms -> 8sec),因为现在自动使用为另一个用例创建的二级索引。
Cloud-Spanner-Web-Query 的“解释”告诉我使用了二级索引。如果我更改排序(仅出于测试目的)或提供 FORCE_INDEX 查询又会很快。
我可以使用Cloud Spanner 查询语法文档中记录的FORCE_INDEX=_BASE_TABLE来“解决”这个问题。
我的问题是:我真的必须为每个查询都这样做以避免这种影响吗?
这将查询定义与索引定义混合在一起,恕我直言,这不是一件好事。
具有主索引的表:
CREATE TABLE change_history (
userId INT64 NOT NULL,
createdAtUnique INT64 NOT NULL,
itemId STRING(512) NOT NULL,
newValue FLOAT64 NOT NULL,
oldValue FLOAT64 NOT NULL,
) PRIMARY KEY (userId, itemId, createdAtUnique DESC)
二级指标:
CREATE INDEX ch_userid_createdatunique_all ON change_history (
userId,
createdAtUnique
) STORING (
newValue,
oldValue
)
原始查询:
SELECT * FROM change_history WHERE
userId = 2563
AND itemId = "215414"
AND createdAtUnique >= 15385766670000000
AND createdAtUnique <= 15465254670000000 ORDER BY createdAtUnique
我希望查询继续使用它设计的主键。
但是通过添加二级索引,查询开始使用这个索引而不是主键。
解决方案
在这种情况下,查询优化器决定选择索引,因为 1) 它是覆盖的;2) 避免在原始计划中进行排序,因为索引包含createdAtUnique
升序排序,这是查询中请求的排序顺序。但是,对于您的数据分布,这被证明是一个糟糕的选择。
通常,对于经过手动调整以获得您知道是最佳/良好的特定计划的查询,最好在查询中使用force_index
和join_type
提示来防止优化器可能选择不同计划的罕见实例。
推荐阅读
- ssl - 当我在 apache2 ubuntu 服务器上启用 SSL 时,http 和 https 都不起作用
- python - SqlAlchemy 查询深层嵌套对象
- r - 如何使用 ggplot2 中使用的 mean_CI_boot 计算自举置信区间?
- python - 为什么我收到此消息无效语法?
- scala - 如何以最有效的方式删除 spark RDD 的标题行?
- c - 设计带有分叉的多客户端服务器
- api - AppleScript 不起作用,安装了 JSON Helper
- spring - 使用 spring boot 和 h2 读取数据库对象
- c# - 使用 Selenium C# 单击网页上更新的最近链接
- email - 如何格式化 DKIM 标题和正文?