Отслеживать мутированные строки в BigQuery? - PullRequest
1 голос
/ 19 февраля 2020

У меня есть большая таблица, строки которой периодически обновляются / вставляются / объединяются из нескольких разных запросов. Мне нужно запустить запланированный процесс (через API), чтобы периодически проверять, какие строки в этой таблице были обновлены с момента последней проверки. Итак, вот мои проблемы ...

  • Когда я запускаю запрос на слияние, я не вижу способа, чтобы он возвратил, какие записи были обновлены ... в противном случае, я мог бы копировать эти обновленные записи. строк в специальной таблице updated_records.
  • Триггеров нет, поэтому я не могу отслеживать мутации таким образом.
  • Я мог бы добавить столбец отметки времени last_updated, чтобы отслеживать это, но затем многократный запрос всей таблицы в течение всего дня потребует огромного количества данных (дорого).

Мне интересно, пропускаю ли я что-то очевидное или, может быть, есть какие-то специальные метаданные BQ, которые могут помочь?

Причина, по которой я пытаюсь это сделать, заключается в том, что я я хочу извлечь и синхронизировать меньшее подмножество этой таблицы в мой экземпляр PostgreSQL, потому что задержка для запроса BQ слишком велика для небольших запросов.

Есть идеи? Спасибо!

Ответы [ 4 ]

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

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

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

PS Подробное объяснение

Я мог бы добавить столбец отметки времени last_updated, чтобы отслеживать этот путь

Из этого я сделал вывод, что столбца last_updated еще нет (поэтому проверка Оператор for-updates в настоящее время не может различать guish между обновленными и не обновленными строками), но вы можете изменить операторы таблицы UPDATE, чтобы этот столбец был добавлен во вновь измененные строки.

Поэтому Я предположил, что вы можете изменить обновления дальше, чтобы установить дополнительный столбец last_updated_date, который будет содержать часть даты временной отметки, хранящейся в столбце last_updated.

, но затем многократно запрашивать всю таблицу день

Отсюда я сделал вывод, что в течение дня происходит несколько проверок.

, но обновляемые данные могут быть за любой период времени

Конечно, но как только строка будет обновлена, независимо от того, сколько ей лет, она получит два новых столбца last_updated и last_updated_date - если оба столбца уже не были добавлено предыдущим обновлением, и в этом случае два столбца будут обновлены, а не добавлены. Если между проверками обновлений имеется несколько обновлений в одной и той же строке, то последнее обновление все же сделает строку доступной для обнаружения при проверках, использующих лог c, описанную ниже.

Проверка для Оператор обновления будет (концептуально, а не буквально):

  • фильтровать строки для обеспечения last_updated_date=today AND last_updated>last_checked. Дата и время предыдущей проверки обновлений будут храниться в last_checked, и место хранения этого фрагмента данных (таблица, долговременная конфигурация) зависит от реализации.

  • обнаружение, является ли текущая проверка первая сегодняшняя проверка. Если это так, то дополнительно ищите last_updated_date=yesterday AND last_updated>last_checked.

Примечание 1 Если таблица разделена и / или кластеризована в столбце last_updated_date, то вышеупомянутые проверки обновлений не вызовут сканирование таблицы. И с учетом «скромного» предположения, сделанного в самом начале моего ответа, проверки удовлетворят ваш третий пункт.

Примечание 2 Недостатком этого подхода является то, что при проверках обновлений не будут обнаружены строки, которые были обновлены до того, как были изменены операторы таблицы UPDATE, чтобы включить два дополнительных столбца. (Такие строки будут в разделе __NULL__ со строками, которые никогда не обновлялись.) Но я предполагаю, что до внесения изменений в операторы UPDATE невозможно будет различить guish между обновленными строками и не обновленными все равно.

Примечание 3 Это объяснительная концепция. В реальной реализации вам может понадобиться один дополнительный столбец вместо двух. И вам нужно будет проверить, какой подход работает лучше: разбиение или кластеризация (с разбиением на поддельный столбец) или и то, и другое.

Подробное объяснение исходного (например, выше PS ) заканчивается здесь.

Примечание 4

только кластеризация помогает повысить производительность

С точки зрения предотвращения сканирования таблиц и достижения сокращения использования данных / затраты, одна кластеризация (с поддельным разделением) может быть такой же мощной, как и разделение.

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

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

Подход состоит в том, чтобы иметь 3 таблицы:

  1. одна basetable в режиме «только добавление», добавляются только вставки и обновления в виде полной строки, в этой таблице будет каждая запись как система управления версиями.
  2. таблица для хранения deletes (или это можно включить как мягкое удаление, если в первой таблице хранится специальный столбец)
  3. a livetable, где вы храните текущий данные (в этой таблице вы, скорее всего, сделаете свои операторы MERGE из первой базовой таблицы.

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

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

Одним из способов является периодическое сохранение промежуточного состояния таблицы с использованием функции перемещения во времени. Или хранить только различия. Я просто хочу оставить эту опцию здесь:

FOR SYSTEM_TIME AS OF ссылается на исторические версии определения таблицы и строки, которые были текущими в timestamp_expression.

Значение timestamp_expression должно быть в пределах за последние 7 дней .

Следующий запрос возвращает хронологическую версию таблицы за один час go.

SELECT * FROM table
  FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR);

Следующий запрос возвращает хронологическую версию таблицы в абсолютный момент времени.

SELECT * FROM table
  FOR SYSTEM_TIME AS OF '2017-01-01 10:00:00-07:00';
0 голосов
/ 05 марта 2020

Некоторые хорошие идеи размещены здесь. Спасибо тем, кто откликнулся. По сути, есть несколько подходов к решению этой проблемы.

Но в любом случае, вот как я решил свою конкретную проблему ...

Предположим, что данные должны в конечном итоге оказаться в таблице с именем MyData . Я создал две дополнительные таблицы: MyDataStaging и MyDataUpdate . Эти две таблицы имеют структуру, идентичную MyData , за исключением MyDataStaging имеет дополнительное поле Timestamp, "batch_timestamp". Эта временная метка позволяет мне определить, какие строки являются последними версиями в случае, если до обработки таблицы у меня будет несколько версий.

DatFlow передает данные непосредственно в MyDataStaging вместе с меткой времени ( "batch_timestamp") значение, указывающее, когда процесс запущен. Запланированный процесс затем переносит / объединяет MyDataStaging в MyDataUpdate ( MyDataUpdate теперь всегда будет содержать только уникальный список строк / значений, которые были изменены). Затем процесс переносит / объединяет из MyDataUpdate в MyData , а также экспортирует и загружает для загрузки в PostgreSQL. Затем таблицы размещения / обновления очищаются соответствующим образом.

Теперь я не постоянно запрашиваю массивную таблицу для проверки изменений.

ПРИМЕЧАНИЕ. При слиянии с основной большой таблицей я фильтрую обновление на уникальные даты из исходной таблицы, чтобы ограничить количество обрабатываемых байтов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...