Как Google хранит ваши большие таблицы запросов и как это влияет на вас

Опубликовано: 2016-02-24

Это техническая инсталляция нашего блога, представленная выдающимся разработчиком Адамом Ноксом.

Хотя Big Query использует синтаксис, очень похожий на SQL, на самом деле он использует совершенно иной подход, чем решение для обработки больших объемов данных. Big Query имеет тенденцию к грубой силе и фактически не использует индексы, поэтому большое количество данных означает много процессоров и времени обработки. Чтобы добиться этого, Google применил другой способ хранения данных, который может повлиять на то, как вы разрабатываете свои запросы.

Формат файла

Когда создается таблица, Google использует свой формат ColumnIO для хранения ваших данных. Каждый столбец хранится в виде отдельного файла, за исключением повторяющихся полей. Если у вас есть таблица со столбцами: имя (строка), phoneNumbers (повторяющееся целое число); имя будет храниться в одной строке с другими именами, а все номера телефонов, связанные с этим именем, будут храниться в одной строке с номерами телефонов. Столбцы также могут быть разделены, если они станут слишком большими, но это не повлияет на рабочий процесс.

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

Файловое хранилище

Если вы создали таблицу, вы можете быть в достаточной степени уверены, что она никуда не денется, потому что после создания ваши файлы хранятся в трех разных центрах обработки данных и даже в трех разных местах в каждом центре обработки данных. Поскольку Big Query заставляет процессоры решать проблемы, данные должны быть легко доступны. Предостережение — это временные наборы данных. Существует возможность указать время истечения срока действия для таблиц в наборе данных, и таблицы исчезнут, как только они станут старше этой даты истечения срока действия.

Иерархия таблиц

Проекты имеют возможность хранить наборы данных, каждый из которых может содержать таблицы. Полная команда для доступа к таблице в синтаксисе Big Query — [projectname:datasetname.tablename] , однако ее можно сократить до dataset.tablename , если вы обращаетесь к таблице из проекта, над которым работаете в данный момент.

Разбиение связанных данных на отдельные таблицы (например, по дате или после определенного события) может быть полезно для создания более удобных для сопровождения запросов, поскольку запросы обычно выполняются по всем строкам в таблице. Это означает, что вы можете просмотреть несколько таблиц, поэтому в каждом наборе данных скрыта так называемая метатаблица, доступная по адресу [projectname:datasetname.__TABLES__] и содержащая информацию о каждой таблице в наборе данных, которую можно использовать для агрегирования таблиц для запрос.

Команда TABLE_QUERY — это команда, которая позволяет агрегировать несколько похожих таблиц перед выполнением запроса к агрегации, и любой столбец в __TABLES__ может использоваться для формирования этой агрегации. Например, если мне нужно получить представление о времени отклика для проекта с 1 января 2016 года, я могу выполнить следующий запрос, который показывает минимальное, среднее и максимальное время отклика:

 SELECT QUANTILES((protoPayload.endTime - protoPayload.startTime), 3) AS responseTimeBucketsInMilliseconds FROM (TABLE_QUERY(appengine_logs, "table_id CONTAINS 'appengine_googleapis_com_request_log' AND creation_time > 1451606400000"))

Поскольку используются только два столбца, каждый из которых содержит целые числа, это все еще достаточно дешевый запрос (0,0003 доллара США), даже несмотря на то, что он обращается к 28+, что, как мне сказали, составляет 1,857 ТБ по приведенному ниже запросу, и будет стоить около 9 долларов для доступа к каждому полю из .

 SELECT SUM(size_bytes)/1000000000 FROM [repcore-prod:appengine_logs.__TABLES__] WHERE table_id CONTAINS 'appengine_googleapis_com_request_log' AND creation_time > 1451606400000

Обновление файлов

Big Query отлично подходит для регистрации изменений и анализа этих изменений, потому что вы можете передавать новые строки в таблицу. Однако это ужасное устройство хранения данных для быстрого и частого поиска определенных строк из-за отсутствия индексов, а также не подходит для хранения единичных представлений объектов, которые вы ожидаете изменить, потому что строки в таблице нельзя изменить или удалить. .

Разделительные столы

В некоторых ситуациях даже доступ к одному столбцу слишком сложен для обработки в Big Query. Представляю вам следующий непригодный для использования запрос, который возвращает идентификаторы листинга в порядке даты создания листинга:

 SELECT lid FROM [repcore-prod:datastore.LIS] ORDER BY ct

Технически это недавно стало возможным, но не для людей в Vendasta, потому что это требует включения более высокого уровня выставления счетов. Поскольку нет предварительно упорядоченных индексов, он очень интенсивно обрабатывает небольшой объем данных, поэтому в этом случае они взимают плату за обработку. Изменить уровень выставления счетов можно в интерактивных запросах в пользовательском интерфейсе Big Query, отметив «разрешить неограниченное количество» (если включено) под кнопкой «Параметры».

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

Вы можете узнать больше о декораторах столов здесь. В отличие от фильтрации результатов с помощью таких команд, как LIMIT/WHERE/HAVING/OMIT , декораторы таблиц на самом деле снижают стоимость запросов к таблице, потому что они даже не будут получать доступ к данным за пределами заданного диапазона. К сожалению, этот метод почти бесполезен в Vendasta, потому что даже для таких таблиц, как ListingHistoryModel, в которые мы фактически выполняем потоковую передачу, мы по-прежнему удаляем всю таблицу и заменяем ее каждый день репликой, если она из NDB, что означает, что декораторы табличного времени будут работать только на ListingHistoryModel, если вас интересуют только записи текущего дня.

Просмотр журналов — это единственное место, где они могут быть весьма полезны в Vendasta. Из-за размера фактического содержимого журнала легко достичь пределов вычислений и памяти, а запрос даже только столбца содержимого журнала обходится дорого. С журналами обычно также заботятся только о конкретных моментах времени, и это именно то, с чем помогает декоратор времени.

Результаты запроса

Каждый раз, когда вы запускаете запрос, он создает новую таблицу и иногда создает неизвестные скрытые таблицы за кулисами. Если вы так выберете, вы можете дать таблице результатов имя, чтобы сохранить ее, или оставить ее с именем, которое дал ей Google, и позволить ей исчезнуть через день. Если вы когда-нибудь столкнетесь с сообщением «Слишком большой ответ, чтобы вернуться», это потому, что они защищают вас от вас самих. Легко создавать огромные таблицы (особенно с перекрестными соединениями). Если это произойдет, и вы ожидали, что это произойдет, вам необходимо указать имя таблицы и включить параметр «Разрешить большие результаты». Если вы повторяете запрос, к которому не передаются новые строки, вы просто получите кешированные результаты, если они все еще существуют.