Como o Google armazena suas tabelas do Big Query e como isso afeta você
Publicados: 2016-02-24Esta é uma instalação de conversa técnica do nosso blog, trazida a você pelo extraordinário desenvolvedor Adam Knox.
Embora o Big Query use uma sintaxe muito semelhante ao SQL, na verdade é preciso um tato significativamente diferente para uma solução para processar grandes quantidades de dados. O Big Query tem uma tendência a força bruta e não usa índices, então muitos dados significam muitos processadores e tempo de processamento. Para conseguir isso, o Google adotou uma maneira diferente de armazenar dados que podem afetar a maneira como você projeta suas consultas.
Formato de arquivo
Quando uma tabela é criada, o Google usa o formato ColumnIO para armazenar seus dados. Cada coluna é armazenada como um arquivo separado, com exceção de campos repetidos. Se você tiver uma tabela com as colunas: name (string), phoneNumbers (inteiro repetido); o nome será armazenado em uma única linha com os outros nomes e todos os números de telefone associados a esse nome serão armazenados em uma única linha com os números de telefone. As colunas também podem ser divididas se ficarem muito grandes, mas isso não afetará o fluxo de trabalho.
Saber disso fornece a capacidade de executar consultas mais rápidas, não processando colunas com as quais você realmente não se importa e, em alguns casos, até torna possível executar consultas anteriormente impossíveis. As consultas também podem ficar mais baratas, pois o sistema cobra pela quantidade de dados processados e, se uma coluna não for incluída na consulta, esses dados não serão processados.
Armazenamento de arquivo
Se você criou uma tabela, pode se sentir razoavelmente seguro de que ela não vai a lugar nenhum, porque, depois que seus arquivos são criados, eles são armazenados em três data centers diferentes e até em três locais diferentes em cada data center. Como o Big Query causa problemas aos processadores, os dados precisam estar prontamente acessíveis. A ressalva para isso são conjuntos de dados temporários. Há uma opção para especificar um tempo de expiração para tabelas em um conjunto de dados e as tabelas desaparecerão quando forem mais antigas que essa data de expiração.
Hierarquia da Tabela
Um projeto tem a capacidade de armazenar conjuntos de dados, que podem conter tabelas. O comando completo para acessar uma tabela na sintaxe do Big Query é [projectname:datasetname.tablename]
, mas pode ser abreviado para dataset.tablename
se você estiver acessando a tabela a partir do projeto em que está trabalhando no momento.
Dividir os dados relacionados em tabelas separadas (por exemplo: por data ou após a ocorrência de um evento específico) pode ser benéfico para fazer consultas mais fáceis de manter, pois as consultas geralmente são executadas em todas as linhas de uma tabela. Isso significa que você pode querer examinar várias tabelas, então há algo chamado metatabela oculta em cada conjunto de dados que pode ser acessada em [projectname:datasetname.__TABLES__]
e contém informações sobre cada tabela no conjunto de dados e pode ser usada para agregar tabelas para questionando.
O comando TABLE_QUERY
é um comando que permite que várias tabelas semelhantes sejam agregadas antes de executar uma consulta no agregado, e qualquer coluna em __TABLES__
pode ser usada para formar esse agregado. Por exemplo, se eu quiser ter uma ideia dos tempos de resposta desde 1º de janeiro de 2016 para um projeto, posso executar a seguinte consulta que mostra os tempos de resposta mínimo, médio e máximo:
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"))
Como apenas duas colunas contendo números inteiros são usadas, essa ainda é uma consulta razoavelmente barata (US $ 0,0003), mesmo que esteja acessando 28+ que me disseram ter 1,857 TB pela consulta abaixo e custaria cerca de 9 $ para acessar todos os campos de .

SELECT SUM(size_bytes)/1000000000 FROM [repcore-prod:appengine_logs.__TABLES__] WHERE table_id CONTAINS 'appengine_googleapis_com_request_log' AND creation_time > 1451606400000
Atualizando arquivos
O Big Query é ótimo quando se trata de registrar alterações e analisá-las porque você pode transmitir novas linhas para uma tabela. É, no entanto, um péssimo dispositivo de armazenamento de dados para pesquisas rápidas e frequentes de linhas específicas devido à falta de índices, e também não é ótimo para armazenar representações singulares de objetos que você espera alterar porque as linhas em uma tabela não podem ser modificadas ou removidas .
Dividindo Tabelas
Em algumas situações, até mesmo o acesso a uma única coluna é demais para lidar no Big Query. Apresento a você a seguinte consulta inutilizável que retorna IDs de listagem por ordem de data de criação da listagem:
SELECT lid FROM [repcore-prod:datastore.LIS] ORDER BY ct
Tecnicamente, recentemente tornou-se possível que isso fosse bem-sucedido, mas não para as pessoas da Vendasta porque requer habilitar um nível de faturamento mais alto. Como não há índices pré-encomendados, ele está processando uma pequena quantidade de dados com muita intensidade, portanto, neste caso, eles estão cobrando pelo processamento. A alteração do nível de faturamento pode ser feita em consultas interativas na IU do Big Query marcando "permitir ilimitado" (se ativado) no botão "opções".
Supondo que sua consulta seja a mais eficiente possível, existem algumas abordagens restantes para reduzir os tamanhos das tabelas para contornar esses tipos de limites rígidos. O primeiro é decorador de mesa e o segundo é com um hash.
Você pode aprender mais sobre decoradores de mesa aqui. Ao contrário de filtrar os resultados usando comandos como LIMIT/WHERE/HAVING/OMIT
, os decoradores de tabela diminuirão o custo de consultar uma tabela porque nem acessarão os dados fora do intervalo fornecido. Infelizmente, esse método é quase inútil na Vendasta porque mesmo para tabelas como o ListingHistoryModel para o qual realmente transmitimos, ainda descartamos a tabela inteira e a substituímos todos os dias por uma réplica se for do NDB, o que significa que os decoradores de horário da tabela só funcionarão no ListingHistoryModel se você se importa apenas com as entradas do dia atual.
Observar o registro é o único lugar em que eles podem ser bastante úteis na Vendasta. Devido ao tamanho do conteúdo real do log, os limites de computação e memória são fáceis de atingir, e consultar apenas a coluna de conteúdo do log é caro. Com logs, geralmente também se preocupa apenas com pontos específicos no tempo, que é exatamente com o que o decorador de tempo ajuda.
Resultados da consulta
Toda vez que você executa uma consulta, ela cria uma nova tabela e às vezes cria tabelas ocultas desconhecidas nos bastidores. Se você quiser, pode dar um nome à tabela de resultados para mantê-la ou deixá-la com o nome que o Google deu e deixá-la desaparecer após um dia. Se alguma vez você se deparar com uma “resposta grande demais para retornar”, é porque eles estão protegendo você de si mesmo. É fácil criar tabelas enormes (especialmente com junções cruzadas). Se isso acontecer e você esperava que acontecesse, você deve nomear a tabela e ativar a opção “Permitir resultados grandes”. Se você repetir uma consulta que não tenha novas linhas transmitidas para ela, obterá apenas os resultados em cache se eles ainda estiverem por perto.
