Cloud Spanner использует вторичный индекс, когда он не должен

Существующий запрос, который выполнялся быстро с использованием первичного ключа, значительно замедлился (10 мс -> 8 с) без уведомления, поскольку вторичный индекс, созданный для другого варианта использования, теперь используется автоматически.

"Объяснение" Cloud-Spanner-Web-Query говорит мне, что используется вторичный индекс. Если я изменю порядок (только для целей тестирования) или предоставлю FORCE_INDEX, запрос снова будет быстрым.

Я могу "исправить" эту проблему, используя FORCE_INDEX=_BASE_TABLE, которая описана в документации по синтаксису запроса Cloud Spanner.

Мой вопрос: действительно ли я должен делать это для каждого запроса, чтобы избежать таких эффектов?

Это смешивает определение запроса с определением индекса, что не очень хорошо, ИМХО.

Таблица с первичным индексом:

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 ответ

Решение

Оптимизатор запросов в этом случае решил выбрать индекс, потому что 1) он покрывает и 2) избегает сортировки в первоначальном плане, потому что индекс содержит createdAtUnique в порядке возрастания сортировки, который является порядком сортировки, запрашиваемым в запросе. Однако, для вашего распространения данных это оказалось плохим выбором.

В целом, для запросов, которые были настроены вручную для получения определенного плана, который, как вы знаете, является оптимальным / хорошим, целесообразно использовать force_index а также join_type подсказки в запросе для защиты от редкого случая, когда оптимизатор может выбрать другой план.

Другие вопросы по тегам