Cómo almacena Google sus tablas de consultas grandes y cómo le afecta
Publicado: 2016-02-24Esta es una instalación de charla técnica de nuestro blog, presentada por el extraordinario desarrollador, Adam Knox.
Aunque Big Query usa una sintaxis muy similar a SQL, en realidad requiere un tacto significativamente diferente a una solución para procesar grandes cantidades de datos. Big Query tiene una tendencia a usar fuerza bruta y en realidad no usa índices, por lo que muchos datos significan muchos procesadores y tiempo de procesamiento. Para lograr esto, Google ha optado por una forma diferente de almacenar datos que pueden afectar la forma en que diseña sus consultas.
Formato de archivo
Cuando se crea una tabla, Google usa su formato ColumnIO para almacenar sus datos. Cada columna se almacena como un archivo separado con la excepción de los campos repetidos. Si tiene una tabla con las columnas: nombre (cadena), números de teléfono (entero repetido); el nombre se almacenará en una sola línea con los otros nombres y todos los números de teléfono asociados con ese nombre se almacenarán en una sola línea con los números de teléfono. Las columnas también se pueden dividir si son demasiado grandes, pero eso no afectará el flujo de trabajo.
Saber esto brinda la capacidad de ejecutar consultas más rápidas al no procesar columnas que realmente no le interesan y, en algunos casos, incluso hace posible que antes fuera imposible ejecutar consultas. Las consultas también pueden abaratarse ya que el sistema cobra por la cantidad de datos procesados, y si una columna no está incluida en la consulta, entonces esos datos no se procesan.
Almacenamiento de archivos
Si ha creado una tabla, puede sentirse razonablemente seguro de que no irá a ninguna parte, porque una vez que se crean los archivos, se almacenan en tres centros de datos diferentes e incluso en tres lugares diferentes dentro de cada centro de datos. Dado que Big Query arroja problemas a los procesadores, los datos deben ser fácilmente accesibles. La advertencia a esto son los conjuntos de datos temporales. Hay una opción para especificar un tiempo de caducidad para las tablas dentro de un conjunto de datos y las tablas desaparecerán una vez que sean más antiguas que esta fecha de caducidad.
Jerarquía de tablas
Un proyecto tiene la capacidad de almacenar conjuntos de datos, cada uno de los cuales puede contener tablas. El comando completo para acceder a una tabla en la sintaxis de Big Query es [projectname:datasetname.tablename]
, sin embargo, esto se puede acortar a dataset.tablename
si está accediendo a la tabla desde el proyecto en el que está trabajando actualmente.
Dividir los datos relacionados en tablas separadas (por ejemplo, por fecha o después de que ocurra un evento específico) puede ser beneficioso para realizar consultas más fáciles de mantener, ya que las consultas generalmente se ejecutan en todas las filas de una tabla. Esto significa que es posible que desee ver varias tablas, por lo que hay algo llamado metatabla oculta en cada conjunto de datos a la que se puede acceder en [projectname:datasetname.__TABLES__]
y contiene información sobre cada tabla en el conjunto de datos y se puede usar para agregar tablas para consultando
El comando TABLE_QUERY
es un comando que permite agregar varias tablas similares antes de ejecutar una consulta en el agregado, y cualquier columna en __TABLES__
se puede usar para formar este agregado. Por ejemplo, si quiero tener una idea de los tiempos de respuesta desde el 1 de enero de 2016 para un proyecto, podría ejecutar la siguiente consulta que muestra los tiempos de respuesta mínimo, medio y 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"))
Dado que solo se usan dos columnas, cada una de las cuales contiene números enteros, esta sigue siendo una consulta razonablemente barata ($ 0.0003), a pesar de que está accediendo a más de 28 que me dijeron que son 1.857 TB por la consulta a continuación y costaría alrededor de $ 9 para acceder a cada campo desde .

SELECT SUM(size_bytes)/1000000000 FROM [repcore-prod:appengine_logs.__TABLES__] WHERE table_id CONTAINS 'appengine_googleapis_com_request_log' AND creation_time > 1451606400000
Actualización de archivos
Big Query es excelente cuando se trata de registrar cambios y analizar dichos cambios porque puede transmitir nuevas filas a una tabla. Sin embargo, es un dispositivo de almacenamiento de datos terrible para búsquedas rápidas y frecuentes de filas específicas debido a la falta de índices, y tampoco es excelente para almacenar representaciones singulares de objetos que espera cambiar porque las filas de una tabla no se pueden modificar o eliminar. .
Mesas Divisorias
En algunas situaciones, incluso acceder a una sola columna es demasiado complicado en Big Query. Les presento la siguiente consulta inutilizable que devuelve los ID de lista por orden de fecha de creación de lista:
SELECT lid FROM [repcore-prod:datastore.LIS] ORDER BY ct
Técnicamente, recientemente se hizo posible que esto tuviera éxito, pero no para la gente de Vendasta porque requiere habilitar un nivel de facturación más alto. Como no hay índices preordenados, está procesando una pequeña cantidad de datos de manera muy intensiva, por lo que en este caso están cobrando por el procesamiento. Se puede cambiar el nivel de facturación en consultas interactivas en la interfaz de usuario de Big Query marcando "permitir ilimitado" (si está habilitado) en el botón "opciones".
Suponiendo que su consulta sea lo más eficiente posible, quedan un par de enfoques para reducir el tamaño de las tablas para sortear este tipo de límites estrictos. El primero es decoradores de tiempo de mesa y el segundo es con un hash.
Puede obtener más información sobre los decoradores de mesa aquí. A diferencia de filtrar los resultados usando comandos como LIMIT/WHERE/HAVING/OMIT
, los decoradores de tablas en realidad reducirán el costo de consultar una tabla porque ni siquiera accederá a los datos fuera del rango dado. Desafortunadamente, este método es casi inútil en Vendasta porque incluso para tablas como ListingHistoryModel a las que realmente transmitimos, aún descartamos la tabla completa y la reemplazamos todos los días con una réplica si es de NDB, lo que significa que los decoradores de tiempo de mesa solo funcionarán en el ListingHistoryModel si solo le interesan las entradas del día actual.
Mirar el registro es el único lugar en el que pueden ser muy útiles en Vendasta. Debido al tamaño del contenido real del registro, los límites de cálculo y memoria son fáciles de alcanzar, y consultar incluso la columna de contenido del registro es costoso. Con los registros, por lo general, uno solo se preocupa por puntos específicos en el tiempo, que es exactamente con lo que ayuda el decorador de tiempo.
Resultados de la consulta
Cada vez que ejecuta una consulta, crea una nueva tabla y, a veces, crea tablas ocultas desconocidas detrás de escena. Si así lo elige, puede asignar un nombre a la tabla de resultados para mantenerla, o dejar que se quede con el nombre que Google le dio y dejar que desaparezca después de un día. Si alguna vez te encuentras con una "Respuesta demasiado grande para devolverla", es porque te están protegiendo de ti mismo. Es fácil crear tablas enormes (especialmente con uniones cruzadas). Si esto sucede y esperaba que sucediera, debe nombrar la tabla y habilitar la opción "Permitir resultados grandes". Si repite una consulta que no tiene nuevas filas transmitidas, solo obtendrá los resultados almacenados en caché si todavía están disponibles.
