Увеличение значений в Google Cloud Spanner - PullRequest
0 голосов
/ 16 февраля 2020

Я использую Google Cloud Spanner, и мне нужен способ увеличить значение строки на value = value + 1. Это оказывается большой головной болью, потому что я не вижу способа проверить, существует ли уже строка. Я использую клиентскую библиотеку Ruby (gem версия 1.13.1)

В настоящее время у меня есть следующий код, который выполняет эту работу, но только со скоростью около 40-50 транзакций в секунду. Я не вижу способа пакетировать это, потому что, как я понимаю, я могу пакетировать только отдельные операторы DML.

db.transaction do |transaction|
  if transaction.execute_query("SELECT value FROM table WHERE key = 'ABC'").rows.first.to_h[:value]
    transaction.execute_update("UPDATE table SET value = value + 1 WHERE key = 'ABC'")
  else
    transaction.execute_update("INSERT INTO table (key, value) VALUES ('ABC', 1)")
  end
end

К сожалению SQL, чтобы решить это с помощью одного оператора, кажется, не поддерживается в все. (Я получаю Google::Cloud::InvalidArgumentError (3:Syntax error: Unexpected keyword ON)

db.transaction do |tx|
  tx.batch_update do |b|
    b.batch_update(
      "INSERT INTO table (key, value) VALUES ('ABC', 1) ON DUPLICATE KEY UPDATE value = value + 1"
    )
  end
end

Это также не представляется возможным увеличить с помощью мутаций. Это просто создаст строку или перезапишет значение:

db.transaction do |tx|
  tx.upsert "test", [{ key: 'ABC', value: 1 }]
end

Есть ли способ сделать то, что мне нужно, с помощью Spanner вообще? Медленное многорядное решение действительно печально по сравнению с производительностью пакетной записи со скоростью 100 000 строк в секунду.

1 Ответ

2 голосов
/ 19 февраля 2020

Нет простого способа выполнить sh то, что вам нужно.

Один из вариантов, чтобы убедиться, что мы получили разумную пропускную способность:

  1. Выполните чтение всех ключей, которые вы хотите обновить или вставить.
  2. Создайте BatchDML с помощью куча операторов вставки / обновления, основанных на результатах операций чтения с шага № 1.
  3. Обратите внимание, что обновления должны быть условными обновлениями. Пример: "Значение SET таблицы UPDATE = {prev_value} +1 ключ WHERE =" AB C "И значение = {prev_value}";
  4. Выполнить построенный BatchDML. Обратите внимание, что некоторые операторы могут завершиться ошибкой.

    Вставки могут завершиться ошибкой, если ключ уже существует: я считаю, что это не должно быть проблемой, поскольку ключ существует (это желаемый результат для попытки вставки).

    Обновления могут не произойти, если значение изменяется со времени, когда мы читаем. Если мы повторим этот цикл, обновления могут произойти в следующем пакете.

Как вы можете видеть, это идет с предостережениями.

...