Cloud Spanner 在不应该使用的时候使用了二级索引

Chr*_*ter 2 google-cloud-platform google-cloud-spanner

使用主键快速执行的现有查询在没有通知的情况下大幅减慢(10 毫秒 -> 8 秒),因为现在会自动使用为另一个用例创建的二级索引。

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)
Run Code Online (Sandbox Code Playgroud)

二级指标:

CREATE INDEX ch_userid_createdatunique_all ON change_history (
    userId,
    createdAtUnique
) STORING (
    newValue,
    oldValue
)
Run Code Online (Sandbox Code Playgroud)

原始查询:

SELECT * FROM change_history WHERE                         
    userId = 2563
    AND itemId = "215414"
    AND createdAtUnique >= 15385766670000000
    AND createdAtUnique <= 15465254670000000 ORDER BY createdAtUnique
Run Code Online (Sandbox Code Playgroud)

我希望查询继续使用它设计的主键。

但是通过添加二级索引,查询开始使用这个索引而不是主键。

adi*_*adi 5

在这种情况下,查询优化器决定选择索引,因为 1) 它覆盖了 2) 避免了原始计划中的排序,因为索引包含createdAtUnique升序排序,这是查询中请求的排序顺序。但是,对于您的数据分布,结果证明这是一个糟糕的选择。

通常,对于已手动调整以获得您知道最佳/良好的特定计划的查询,最好在查询中使用force_indexjoin_type提示以防止优化器可能选择不同计划的罕见情况。