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

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

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

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

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

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

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

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

Я ожидал, что запрос продолжит использовать первичный ключ, для которого он был разработан.

Но добавив вторичный индекс, запрос начал использовать его вместо первичного ключа.


person Christian Gintenreiter    schedule 03.01.2019    source источник
comment
@adi может продвинуть это до ответа?   -  person RedPandaCurios    schedule 04.01.2019


Ответы (1)


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

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

person adi    schedule 04.01.2019
comment
Спасибо за ответ! Я бы не сказал, что мой запрос был настроен вручную - это было просто первоначальное намерение всей таблицы. Как разработчику мне не нравится это поведение выбора индекса, когда добавление вторичного индекса приводит к плохому выбору исходного использования таблицы ... но это уже другое обсуждение :) - person Christian Gintenreiter; 14.01.2019